home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2006 May / PCpro_2006_05.ISO / files / mobile / fma-2.0-stable-setup.exe / {app} / source / Unit1.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2005-01-29  |  354.3 KB  |  10,752 lines

  1. unit Unit1;
  2.  
  3. {
  4. *******************************************************************************
  5. * Descriptions: Main Unit for FMA
  6. * $Source: /cvsroot/fma/fma/Unit1.pas,v $
  7. * $Locker:  $
  8. *
  9. * Todo:
  10. *   - Replace all 'name + [ + number + ]' with ContactNumberByTel calls
  11. *   - split implementation to different smaller units
  12. *   - refresh calls, should refresh specified folder only
  13. *   - store msg to folder not by pdu but by index and location
  14. *
  15. * Change Log:
  16. * $Log: Unit1.pas,v $
  17. * Revision 1.120.2.13  2005/01/27 10:00:24  z_stoichev
  18. * Fixed: Group member properties now work.
  19. *
  20. * Revision 1.120.2.12  2005/01/26 11:34:24  z_stoichev
  21. * Fixed create logs on exit bug (by vo.x)
  22. *
  23. * Revision 1.120.2.11  2005/01/26 10:16:32  z_stoichev
  24. * Merged with 2.1 Beta 1 bugfixes
  25. *
  26. * Revision 1.120.2.10  2004/12/09 12:50:11  z_stoichev
  27. * Fixed: Upgrade from single DB (some files arent copied).
  28. *
  29. * Revision 1.120.2.9  2004/11/12 08:40:36  z_stoichev
  30. * Battery parsing for K700i fixed
  31. *
  32. * Revision 1.120.2.8  2004/10/15 14:06:20  z_stoichev
  33. * Beta code compatability.
  34. *
  35. * Revision 1.120.2.7  2004/10/15 11:27:58  z_stoichev
  36. * Bugfixes
  37. *
  38. * Revision 1.120.2.6  2004/10/14 16:43:26  z_stoichev
  39. * Bugfixes
  40. *
  41. * Revision 1.120.2.5  2004/09/20 08:32:20  merijnb
  42. * added support for paths with CRLF's and / or spaces in them
  43. *
  44. * Revision 1.120.2.4  2004/09/10 12:10:12  z_stoichev
  45. * - Fixed 'Old data format' error when turn off IrmcSync.
  46. * - Fixed Switch IrmcSync do not remember contact states.
  47. * - Fixed End Windows Session and FMA do not exits.
  48. *
  49. * Revision 1.120.2.3  2004/09/08 19:24:24  lordlarry
  50. * New Line Char in Contact Name is read properly from the Contacts.SYNC.dat file too
  51. *
  52. * Revision 1.120.2.2  2004/09/07 19:30:03  lordlarry
  53. * New Line Char in Contact Name is read properly from the Contacts.ME.dat file (not checked Contacts.SYNC.dat)
  54. *
  55. * Revision 1.120.2.1  2004/09/04 13:49:48  lordlarry
  56. * Enter in contact names throws EAbort when reading from DB. Catched and loged it so FMA doesn't blow. Needs a propper fix.
  57. *
  58. * Revision 1.120  2004/08/27 20:41:59  lordlarry
  59. * Merge from newxml
  60. *
  61. * Revision 1.119.4.2  2004/08/25 15:41:13  merijnb
  62. * added export to xml for SIM entries
  63. *
  64. * Revision 1.119.4.1  2004/08/25 10:54:13  merijnb
  65. * implemented xml parser
  66. *
  67. * Revision 1.119  2004/08/19 12:55:29  merijnb
  68. * contents of sms textbox aren't cleared if the sms compose window was already visible (1003202)
  69. *
  70. * Revision 1.118  2004/08/19 12:27:29  merijnb
  71. * changed the way voice dialling support is deteced since K700 does not support at*evd, but does at*eva and at*evh. this fixed the "can't hangup with k700" bug, since k700 does _not_ support ATH very well
  72. *
  73. * Revision 1.117  2004/08/18 17:16:57  voxik
  74. * Fixed Removed Ifdefs for WinXP.res
  75. *
  76. * Revision 1.116  2004/08/17 20:21:58  merijnb
  77. * little cosmetic thing. Units are now made readable (10.000 mA -> 10 A)
  78. *
  79. * Revision 1.115  2004/08/17 14:49:15  merijnb
  80. * added support for (K700) subfolders (bugfix for 1007256 and 994461)
  81. *
  82. * Revision 1.114  2004/07/26 12:55:55  z_stoichev
  83. * - Fixed Clock sync if hour separator is not colon.
  84. * - Fixed Auto-reconnect loop can be aborted now.
  85. * - Fixed Parse Obex Folders file size ends with 'd' issue.
  86. * - Changed Quote of the day :-D
  87. * - Added Force UCS-2 new text message encoding.
  88. * - Added Power Off phone tools feature.
  89. *
  90. * Revision 1.113  2004/07/25 14:38:35  lordlarry
  91. * - Fixed: Outlook Sync is disabled if IrmcSync is disabled
  92. * - Changed: Options menu item have moved to the Tools menu
  93. *
  94. * Revision 1.112  2004/07/25 13:30:36  lordlarry
  95. * Added the ability to select the Outlook folder where all the New contacts end up.
  96. *
  97. * Revision 1.111  2004/07/24 15:59:04  lordlarry
  98. * D7 compatibility thing fixed
  99. *
  100. * Revision 1.110  2004/07/14 10:04:12  z_stoichev
  101. * - Fixed Do not steal notes focus on active call.
  102. * - Fixed Estimated Time Left displays wrong days.
  103. * - Fixed Disable explorer view during files delete.
  104. *
  105. * Revision 1.109  2004/07/07 11:23:25  z_stoichev
  106. * - Fixed '' is not valid integer on SMS sending.
  107. * - Fixed Call/msg personalized much faster now.
  108. * - Fixed UpdateNewMessagesCounter is failsafe.
  109. * - Added Chat messages are auto-marked as read.
  110. * - Added Chat messages are deleted from phone.
  111. * - Added Chat messages do not open popup window.
  112. * - Added Toggle Silent Mode on/off toolbar buton.
  113. * - Added More startup explorer folder options.
  114. * - Changed Connect/disconnect phone icons.
  115. * - Changed Conection progress indicator.
  116. *
  117. * Revision 1.108  2004/07/06 14:44:42  z_stoichev
  118. * - Fixed Call/msg personalized much faster now.
  119. * - Added K700 subfolders partial support.
  120. *
  121. * Revision 1.107  2004/07/02 20:14:23  z_stoichev
  122. * - Fixed Save Script editor changes issue.
  123. * - Close mutex handle on exit mem leak bugfix.
  124. *
  125. * Revision 1.106  2004/07/02 18:14:16  lordlarry
  126. * Fixed 100% CPU when communicating
  127. *
  128. * Revision 1.105  2004/07/02 08:14:02  z_stoichev
  129. * - Added Sound events for Proximity Away/Near.
  130. *
  131. * Revision 1.104  2004/07/02 07:46:05  z_stoichev
  132. * - Fixed DB upgrade in Save Message To Folder.
  133. * - Fixed DB upgrade in Update Folder Unread Counter.
  134. *
  135. * Revision 1.103  2004/07/01 14:40:23  z_stoichev
  136. * Quote of the day :)
  137. *
  138. * Revision 1.102  2004/06/30 16:13:42  z_stoichev
  139. * - Fixed Sync menu items disabled in offline mode.
  140. * - Fixed FMA main menu changes reapplied.
  141. *
  142. * Revision 1.101  2004/06/30 15:34:01  z_stoichev
  143. * - Fixed New Bookmark action update check.
  144. * - Fixed Ask for unsent messages on exit when minimized.
  145. * - Fixed Hide GUI when starting second Fma instance.
  146. * - Fixed dial wrong number when name contains digits.
  147. * - Fixed WAP Home Page UTF-8 codec support.
  148. * - Added WAP Home Page locked warning message.
  149. * - Added WAP Home Page edit sanity check.
  150. * - Added Add contact number to Phonebook wizard.
  151. * - Added Create/Delete phone contacts Group.
  152. * - Changed Message storage full warning is optional.
  153. *
  154. * Revision 1.100  2004/06/29 15:25:51  z_stoichev
  155. * Add Call support without popups.
  156. * Edit Call Favorites support
  157. * Call Contact confirmation dialog.
  158. * Dont remember what is next :)
  159. *
  160. * Revision 1.99  2004/06/28 22:43:54  z_stoichev
  161. * Delete bugfixes.
  162. *
  163. * Revision 1.98  2004/06/28 15:34:30  z_stoichev
  164. * - Fixed 977988 Files overwritten without Prompt.
  165. * - Fixed 977310 Quotes in phone serial number.
  166. * - Fixed Connection loop if clock sync is on.
  167. * - Fixed Send Message selects message store first.
  168. * - Added Phone message storage is 90% full warning.
  169. * - Added Sync with Outlook on startup option.
  170. * - Added Edit WAP Home Page URL (under Tools).
  171. * - Added Explore phone WAP bookmarks.
  172. * - Added 10 secs delay after Disconnect Temporary.
  173. * - Added Edit Favorites from main menu.
  174. * - Added Delete phone Bookmark.
  175. * - Added Bookmark root folder profile setting.
  176. * - Changed Create new phone bookmark (without Obex).
  177. * - Changed Made Script usage optional (see Options).
  178. * - Changed Low battery warning (typos) (LL).
  179. * - Changed Fma Home page URL to sf.net one.
  180. * - Changed Outlook categories moved to phone profile.
  181. * - Changed Outlook folders moved to phone profile.
  182. * - Changed Favorites list moved to phone profile.
  183. * - Changed TxAndWait communication routine (LL).
  184. * - Changed Main menu has Edit submenu now.
  185. * - Changed Main menu reorganized a lot.
  186. * - Changed Outlook categories Options recoded.
  187. *
  188. * Revision 1.97  2004/06/28 09:13:32  z_stoichev
  189. * TxAndWait Bugfixes.
  190. * 10 secs delay after Disconnect Temporary.
  191. *
  192. * Revision 1.96  2004/06/27 21:49:41  z_stoichev
  193. * Retrieve and Explore phone WAP bookmarks.
  194. * Fixed Connection loop if clock sync is on.
  195. * TxAndWait INFINITE loop changed to 50 ms.
  196. *
  197. * Revision 1.95  2004/06/27 20:26:23  lordlarry
  198. * - Optimized a part of TxAndWait. Didn't help much tho'
  199. * - Corrected some spelling thanks to Astrakaw
  200. *
  201. * Revision 1.94  2004/06/27 11:28:56  z_stoichev
  202. * Fixed bookmarks loading
  203. *
  204. * Revision 1.93  2004/06/25 15:19:05  z_stoichev
  205. * - Fixed 977988 Files overwritten without Prompt.
  206. * - Fixed 977310 Quotes in phone serial number.
  207. * - Fixed 977367 No quotes in imported message PDUs.
  208. * - Fixed Send Message selects message store first.
  209. * - Added Phone message storage is 90% full warning.
  210. * - Added Sync with Outlook on startup option.
  211. * - Added Edit WAP Home Page URL (under Tools).
  212. * - Added JCL exception dialog with Send Report.
  213. *
  214. * Revision 1.92  2004/06/25 08:25:16  z_stoichev
  215. * - Fixed 977310 Quotes in phone serial number.
  216. * - Fixed Send Message selects message store first.
  217. * - Added Phone message storage is 90% full warning.
  218. *
  219. * Revision 1.91  2004/06/24 14:56:02  z_stoichev
  220. * - Fixed Upload Contacts phone type to SIM issues.
  221. * - Fixed Max field length for ME and SM Phonebooks.
  222. * - Fixed Contact name lookup routines use ME phonebook.
  223. * - Changed Connect after unknown number call is entered.
  224. * - Changed Explorer Popup menu reorganized.
  225. * - Added Chat to Contact command to various popup menus.
  226. * - Added Add to Phonebook to various popup menus.
  227. * - Added hit Enter in SIM editor to edit contact.
  228. * - Added Remove favorite item confirmation message.
  229. * - Added Download entire SIM phonebook.
  230. * - Added New SIM editor columns (phone type, status).
  231. * - Broken Phonebook editors Sorting is not remembered.
  232. *
  233. * Revision 1.90  2004/06/24 09:09:33  z_stoichev
  234. * - Fixed Contact name lookup routines use ME phonebook.
  235. * - Added Chat to Contact command to various popup menus.
  236. * - Added Add to Phonebook to various popup menus.
  237. *
  238. * Revision 1.89  2004/06/23 13:52:17  z_stoichev
  239. * Fixed New Message Delete from Archive folder.
  240. * Added Chat to Contact using Text messages.
  241. *
  242. * Revision 1.88  2004/06/22 14:51:37  z_stoichev
  243. * - Fixed SIM database old format detection.
  244. * - Fixed Copy SIM contacts to Phonebook.
  245. * - Fixed Export file type filter misusage/order.
  246. * - Fixed Export messages UTF-8 and html encoding.
  247. * - Fixed Export contacts multiple headers (csv).
  248. * - Fixed Broken Proximity auto re-connect feature.
  249. * - Fixed Incorrect phone detection messages.
  250. * - Fixed SMS Reply focuses message body.
  251. * - Added Fma Today splitters display marker.
  252. * - Added Fma Today open/close panel buttons.
  253. * - Added GetToken double-quotes support.
  254. * - Added Export contacts DisplayName field (csv).
  255. * - Added Import contacts status line feedback.
  256. * - Added Import/Export SIM contacts (vCard only).
  257. * - Added Copy from Phonebook to SIM w/phone type.
  258. *
  259. * Revision 1.87  2004/06/19 16:10:57  lordlarry
  260. * Memory leak fixed in Outlook Sync
  261. *
  262. * Revision 1.86  2004/06/19 15:44:52  lordlarry
  263. * Added more Unicode support
  264. *
  265. * Revision 1.85  2004/06/19 11:18:45  z_stoichev
  266. * - Added Fma Today cotext popup menu.
  267. * - Changed Fma Today page hides explorer.
  268. * - Changed Contact Group icons.
  269. *
  270. * Revision 1.84  2004/06/18 13:51:16  z_stoichev
  271. * - Changed Fma Today hyperlinks buttons.
  272. * - Fixed New Message notification for K700 phones.
  273. * - Added Keypad support K700 models as T610 clone.
  274. *
  275. * Revision 1.83  2004/06/17 13:28:37  z_stoichev
  276. * uEditProfile usage
  277. *
  278. * Revision 1.82  2004/06/16 08:49:00  z_stoichev
  279. * Fixed Use X button to minimize instead close.
  280. * Fixed Disconnect on Windows logout/shutdown.
  281. *
  282. * Revision 1.81  2004/06/15 15:31:39  z_stoichev
  283. * - Fixed 130 MB memory usage on startup.
  284. * - Fixed Recent Missed Calls list management.
  285. * - Fixed Several "is not integer value" issues.
  286. * - Fixed Script Key Monitoring on startup.
  287. * - Changed Load Outlook folders on need only.
  288. * - Added Default contact DisplayName patterns.
  289. * - Added Default Ringing sound support.
  290. * - Added Default Busy sound support.
  291. * - Added Handle RING signals (default sound).
  292. * - Added Second Incoming call is ignored.
  293. * - Added Cancel Incoming call silently support.
  294. * - Added Cancel Outgoing call warning message.
  295. *
  296. * Revision 1.80  2004/06/11 12:30:42  z_stoichev
  297. * Show info while loading Options (outlook folder issue).
  298. *
  299. * Revision 1.79  2004/06/08 19:31:55  lordlarry
  300. * Memory Leak fixed
  301. *
  302. * Revision 1.78  2004/06/05 13:32:55  lordlarry
  303. * Merged with OutlookSync branch
  304. *
  305. * Revision 1.77  2004/05/21 12:04:19  z_stoichev
  306. * Profile context menu and properties.
  307. * Split Fma Today page vertically.
  308. * Key Monitoring bugfix.
  309. * Signal and Battery status optimized.
  310. *
  311. * Revision 1.76  2004/05/21 10:09:05  z_stoichev
  312. * Changed logging handle routines.
  313. *
  314. * Revision 1.75  2004/05/19 18:34:14  z_stoichev
  315. * Build 0.1.0.35c
  316. *
  317. * Revision 1.74  2004/04/15 06:59:57  z_stoichev
  318. * added  GetPartialNumber
  319. *
  320. * Revision 1.73  2004/04/01 15:34:46  z_stoichev
  321. * New Calls data format support
  322. * Unknown contact support
  323. * Do not send message to unknown number
  324. * Get contact display name by tel/name
  325. *
  326. * Revision 1.72  2004/03/31 07:05:20  z_stoichev
  327. * Fixed Load phone database check and show error.
  328. * Fixed New missed call when answered from phone.
  329. * Fixed Show low battery warning after connect.
  330. * Fixed Blink missed calls toolbar button every second.
  331. * Changed Low battery show warning level < 2%,
  332. * Changed Low battery auto-disconnect level < 1%.
  333. * Changed Welcome page renamed to Fma Today.
  334. * Added Fma toolar button for Welcome page.
  335. * Added Main menu shortcut for Activity log.
  336. *
  337. * Revision 1.71  2004/03/28 22:11:17  z_stoichev
  338. * GUI changes
  339. * Add Fma Today toolbar button.
  340. * Fixed wrong Missed cal when answer from phone.
  341. *
  342. * Revision 1.70  2004/03/26 18:37:39  z_stoichev
  343. * Build 0.1.0.35 RC5
  344. *
  345. * Revision 1.69  2004/03/20 16:28:18  z_stoichev
  346. * Changed All Explorer/menu icons (Stefan Jaeger).
  347. * Added fma.ScriptCall(code) COMObject method.
  348. * Added fma.Sleep(msec) COMObject method.
  349. *
  350. * Revision 1.68  2004/03/14 18:50:49  z_stoichev
  351. * Fixed Execute disconnect events before exit.
  352. * Added Refresh messages folder progress dialog.
  353. * Added Send Text message command support check.
  354. * Added Remember and auto-switch to last user Profile.
  355. * Changed Copy/move to archive mark message as read.
  356. * Changed Delayed diagram show on connect.
  357. *
  358. * Revision 1.67  2004/03/12 16:59:32  z_stoichev
  359. * Fixed Long SMS refference number auto-increment.
  360. * Obex Get/PutObject friendly name support.
  361. * Bugfixes and improvements.
  362. *
  363. * Revision 1.66  2004/03/11 15:13:20  z_stoichev
  364. * Fixed Databases mix up on phone change.
  365. * Fixed Explore incorrect view set on database load.
  366. * Fixed Progress dialog do not hide when diagram is shown.
  367. * Fixed Script method call without params gives false error.
  368. * Fixed A typo "garbadge" in Activity log.
  369. * Fixed Note line breaks are not removed anymore.
  370. *
  371. * Revision 1.65  2004/03/09 15:08:59  z_stoichev
  372. * Fixed Connect on startup waits script to initialize.
  373. * Fixed Missed var declaration in Fma script functions.
  374. * Fixed Refresh Phonebook issue when IrmcSync disabled.
  375. * Fixed Load/Save phone database issues and bugfixes.
  376. * Fixed Transmit scheduled AT while in Obex mode.
  377. * Added Force save phone database after Refresh.
  378. * Added Show group member's phone number in Explorer.
  379. * Added Allow multiple member's numbers into a Group.
  380. * Added Sanity check AT command data before transmit it.
  381. * Added Script dialog exit/timeout event support.
  382. * Changed GUI and various Phone explorer icons.
  383. * Changed Do not ask for Outbox connection if Connect on startup option is activated.
  384. *
  385. * Revision 1.64  2004/03/08 13:11:45  z_stoichev
  386. * Fixed Script object.method call with params executin.
  387. * Fixed Web update mail mirror URL.
  388. * Added Connect to Serial port by (user friendly) name.
  389. * GUI changes.
  390. *
  391. * Revision 1.63  2004/03/07 22:12:03  z_stoichev
  392. * Fixed Open SIM Database when Phonebook is selected issue.
  393. * Fixed Holding No/Back button in AM issue.
  394. * Fixed Hide Calling box on Proximity Away.
  395. * Fixed Database folder name is OS safe (Motorolla IMEI issue).
  396. * Fixed Timeout error triggered on unhandle AT response.
  397. * Fixed Abort does not cancel Auto-reconnect feature.
  398. * Added Scrit Object method call with parameters support.
  399. * Added Web Update wizard, allow update/downgrade at once.
  400. * Changed sleep mode while executing AT command.
  401. * Changed Sync Phonebook button merged with Refresh button.
  402. * Changed GUI colors and other Bugfixes.
  403. *
  404. * Revision 1.62  2004/03/07 11:49:08  z_stoichev
  405. * Fixed bug 849905: '@' added at the end of text messages (SMS)
  406. * Fixed Holding No/Back button in AM issue.
  407. * Added Scrit Object calls parameters support.
  408. * Added Web Update wizard, allow update/downgrade at once.
  409. * Changed sleep mode while executing AT command.
  410. * Changed GUI colors.
  411. *
  412. * Revision 1.61  2004/02/04 16:20:20  z_stoichev
  413. * Added UOL.
  414. *
  415. * Revision 1.60  2004/02/04 13:40:58  z_stoichev
  416. * Added Remove Missed call message from phone.
  417. * Added Script object methods calling support.
  418. * Fixed Script function call routines.
  419. * Fixed Scheduled Script call empty func name.
  420. * Fixed Scheduled AT command execute.
  421. *
  422. * Revision 1.59  2004/02/03 16:02:25  z_stoichev
  423. * Fixed Diagram show/hide on proper place (AT) now.
  424. * Fixed AT command execution with separated threads.
  425. * Fixed Auto Re-connect with separated threads.
  426. * Changed Execute AT commands moved into separate thread.
  427. * Changed Script errors are not modal (see Debug/Activiry log now).
  428. * Changed Script re-initialization proccess after script editing.
  429. * Changed Script changes do not require Fma restart anymore.
  430. *
  431. * Revision 1.58  2004/01/30 16:44:57  z_stoichev
  432. * Do not play sound on exit fixed.
  433. *
  434. * Revision 1.57  2004/01/30 16:39:59  z_stoichev
  435. * Made ObexDelete work in silent mode.
  436. * Fixed Minimum Fma toolbar width constraint.
  437. * Fixed Do not ask twice for sending Outbox on exit.
  438. * Fixed Refresh explorer view on message sent.
  439. * Fixed Incorrect phone ID detected on folder change.
  440. * Fixed Power diagram not visible after connect.
  441. * Fixed Inbox/Get messages on startup shows Sent items.
  442. * Fixed Send SMS failure due to too short timeout.
  443. * Added Move new SMS to Archive removes it from phone.
  444. * Added Debug tools option in main menu.
  445. * Added Silent mode sending/deleteing Obex file.
  446. * Changed Do not play Disconnected sound on exit.
  447. *
  448. * Revision 1.56  2004/01/28 17:46:02  z_stoichev
  449. * Fixed New Person action enabled for SIM editor.
  450. * Fixed Mark multiple messages as read/unread.
  451. * Fixed Remember SIM entries state (modified etc).
  452. * Changed No Build contact structure if no SyncIRMC.
  453. * Added Phone memory Contacts editor if no SyncIRMC.
  454. * Added Send modified contacts to phone before Refresh.
  455. *
  456. * Revision 1.55  2004/01/27 15:57:28  z_stoichev
  457. * Fixed Sending long Text Messages frmo Outbox.
  458. * Fixed Extra @ chars displayed for long Text messages.
  459. * Fixed Timeout after Obex send object.
  460. * Fixed Auto reconnect feature support.
  461. * Removed Transmit script AT command scheduler.
  462. * Added Save script code even on script error.
  463. *
  464. * Revision 1.54  2004/01/26 10:36:33  z_stoichev
  465. * Changed TxAndWait implementation (build 29 merge).
  466. * Fixed Clock sync with incorrect time zone.
  467. * Fixed Auto reconnect feature support (not tested).
  468. * Fixed Text Message send reported as unsent, while it was.
  469. * Added Keypad support for SE T610.
  470. * Fixed Send Text Message TP length calculation.
  471. * Fixed Send Text Message Refference when sent.
  472. * Fixed Upload Text Message to phone.
  473. * Fixed EAMI command responces processing.
  474. * Fixed AT Commands execution misplace.
  475. * Fixed Accessories menu Transmit command.
  476. * Fixed Connection failure if Obex fails.
  477. * Added Main Menu changes, Import under tools.
  478. * Added Upload SMS to phone for incoming ones.
  479. * Added Call unknown number when no selection.
  480. * Added Last call duration in Activity log.
  481. *
  482. * Revision 1.53  2004/01/15 14:14:51  z_stoichev
  483. * Added SMS Counter and Warning level.
  484. * Added Explorer Startup folder selection.
  485. * GUI Changes.
  486. *
  487. * Revision 1.52  2004/01/14 15:04:59  z_stoichev
  488. * Pascal Scripting support.
  489. *
  490. * Revision 1.51  2004/01/13 12:37:32  z_stoichev
  491. * Fixed Keypress Monitoring (by Vit Ondruch)
  492. *
  493. * Revision 1.50  2003/12/22 17:37:47  z_stoichev
  494. * Fixed Outbox send failure will delay...
  495. * Restored Auto Updates Wizard mode (user req).
  496. *
  497. * Revision 1.49  2003/12/22 17:28:22  z_stoichev
  498. * Fixed restore proximity status on exit.
  499. * Fixed Timeout popup on connection loss.
  500. * Connection loss check fixed in every 6 seconds.
  501. * Outbox send failure will delay next attempt with 30 secs.
  502. * Removed doubled "new message received" message.
  503. *
  504. * Revision 1.48  2003/12/19 10:04:44  z_stoichev
  505. * Fixed Proximity/Connect issue on exiting Fma.
  506. * Fixed Keyboard Lock/Unlock state on disconnect.
  507. * Added second icon for Keyboard Lock/Unlock.
  508. * Do not show release build in baloon tooltips.
  509. * Do not show baloon tooltips on exiting Fma.
  510. *
  511. * Revision 1.47  2003/12/18 16:41:29  z_stoichev
  512. * Fixed Store Sent Messages to Archive folder.
  513. * Fixed Popup dialog remove on new message (T610).
  514. * Fixed View Caption update on read/unread count change.
  515. * Execute Keypad Event Reporting start/stop commands when busy.
  516. * Keyboard lock/unlock support, added toolbar button and menu option.
  517. * Fma Build shown on main application window's caption.
  518. *
  519. * Revision 1.46  2003/12/17 17:15:22  z_stoichev
  520. * Added Option to turn off notifications for unsent messages.
  521. *
  522. * Revision 1.45  2003/12/17 16:59:26  z_stoichev
  523. * Fixed Delete from message view removes random, but not only
  524. * selected messages (saveing Draft error).
  525. * Fixed Changes made in offline mode lost on connect.
  526. * Fixed Obex freeze because of missplaced FlushOK calls.
  527. * Added Script engine re-initialization on Options exit.
  528. * Added Outbox and Drafts folders for Text Messages.
  529. * Added Send Outbox messages menu command and toolbar button.
  530. * Added Notifications for unsent messages in Outbox.
  531. *
  532. * Revision 1.44  2003/12/16 17:42:59  z_stoichev
  533. * Fixed Option X button to minimize is not being remembered.
  534. * Fixed New message not send to script function due to AV error.
  535. * Fixed Missed call entry shown contact default number instead
  536. * of real one (which was maded the call with).
  537. * New Message received popup removed on phone (T610).
  538. * Removed exception message box on connect error.
  539. *
  540. * Revision 1.43  2003/12/12 17:01:05  z_stoichev
  541. * Removed dublicate Win XP theme support resource.
  542. * Add support for no calls and no profiles on connect.
  543. * sing new Audio Mixer component.
  544. * Add support for deleteing Obex files.
  545. * Frame view look can be customized.
  546. * Check for phone timer interval set to 2 seconds.
  547. *
  548. * Revision 1.42  2003/12/11 15:09:47  z_stoichev
  549. * Fixed Missed calls window list cleared on calls refresh.
  550. * Moveing diagram to the start point on new connection.
  551. * Files summary status information removed.
  552. *
  553. * Revision 1.41  2003/12/11 14:12:49  z_stoichev
  554. * New functions for Obex folders/files.
  555. * WaitASec moved here from uObex.
  556. * Fixed No baloon on outgoing call.
  557. * Detect Auto answering call with headset.
  558. * Battery and Signal pool disabled during a call.
  559. * Check for re-conect / startup connect disabled during a call.
  560. * Automatic Updates url changed to sf.net.
  561. * Automatic Updates doesn't hide main window now.
  562. *
  563. * Revision 1.40  2003/12/09 16:34:37  z_stoichev
  564. * Added Baloon tooltip on Incoming call.
  565. * Added units uStatusDlg and uVersion.
  566. * Added support for Auto Updates.
  567. * Removed warning for running multiple instances.
  568. * Removed Note and Bookmark toolbar icons.
  569. *
  570. * Revision 1.39  2003/12/09 12:05:26  z_stoichev
  571. * Build 0.10.28c + 29a changes without new WaitComplete unit.
  572. *
  573. * Revision 1.38  2003/12/08 10:37:08  z_stoichev
  574. * Fixed KeyPad not enabled issue.
  575. *
  576. * Revision 1.37  2003/12/04 16:32:15  z_stoichev
  577. * Fixed Home page click works again.
  578. * Fixed Edit own card when no connection.
  579. * Fixed auto re-connect feature.
  580. * Fixed AV error on new connection timeout.
  581. * Added Inbox new messages number into Explorer.
  582. * Added timestamp to outgoing/archive messages.
  583. * Added Fma forums web page link.
  584. *
  585. * Revision 1.36  2003/12/03 16:24:26  z_stoichev
  586. * WaitComplete moved into separated thread.
  587. * FlushOK now uses TxAndWait instead.
  588. *
  589. * Revision 1.35  2003/12/02 16:43:32  z_stoichev
  590. * vCard usage changes.
  591. * Added Connecting Obex property - Timers will check it.
  592. * Fixed restore monitoring on app restore.
  593. *
  594. * Revision 1.34  2003/12/01 16:00:50  z_stoichev
  595. * Fixed Exiting application when connecting.
  596. * Fixed Pressing Enter triggers empty TX command.
  597. * Fixed Wait for last command completion when
  598. * disconnecting.
  599. * Fixed Restore proximity status on disconnect.
  600. * Update tray icon hint on phone rename.
  601. * Changed connection tray icon animation.
  602. * Added Edit own business card (Tools).
  603. * Added calls folder refresh action.
  604. * Changes calls and new contact icons.
  605. *
  606. * Revision 1.33  2003/11/28 09:38:06  z_stoichev
  607. * Merged with branch-release-1-1 (Fma 0.10.28c)
  608. *
  609. * Revision 1.32.2.26  2003/11/27 16:09:26  z_stoichev
  610. * Fixed bug 849698 Adding multiline notes add first line only.
  611. * Fixed bug 850125 Delete New Message leaves it in Inbox.
  612. * Fixed sending text message general error.
  613. * Fixed show fatal errors on connect to prevent future
  614. * operation execution.
  615. * Added unicode support to Notes.
  616. * Added sent message sound.
  617. * Added Save draft button to New message window.
  618. *
  619. * Revision 1.32.2.25  2003/11/26 12:52:59  z_stoichev
  620. * Upload multiple files at once.
  621. *
  622. * Revision 1.32.2.24  2003/11/26 12:30:18  z_stoichev
  623. * Dont change explorer selection on reconnect.
  624. * Select All now works with SIM conacts view.
  625. * Fixed Battery and Signal resume on first status
  626. * check when minimized.
  627. * Fixed active call interrupted on new SMS.
  628. * Removed 'times' from charge count info.
  629. * Phone sync fixes.
  630. * Fixed some typos.
  631. *
  632. * Revision 1.32.2.23  2003/11/21 16:36:46  z_stoichev
  633. * Removed test code.
  634. *
  635. * Revision 1.32.2.22  2003/11/21 16:22:08  z_stoichev
  636. * Fixed new message stops Pooling timer issue.
  637. * Fixed AV error when startup connection is aborted.
  638. * Fixed connect on startup option clear flag on failure.
  639. * Fixed New messages processing routines.
  640. * Fixed random false Phone disconnected message.
  641. * Fixed new Missing call display format.
  642. * Fixed last Explorer node was not explored (was ignored).
  643. * Fixed some memory leaks.
  644. * Fixed (maybe, not tested) clear message box in phone
  645. * when new text message is received.
  646. * Battery and Signal monitoring disabled when minimized.
  647. * Show main windows (if needed) on startup connection.
  648. * Phone clock sync add messages to sync log.
  649. * Phone clock sync show error baloon only on update fail.
  650. * Startup operations processed after connect operation.
  651. * Show new message baloon only if new msg queue is empty.
  652. * New message is processed on every second, not all at once.
  653. * Forward message sets cursor position at the end of text.
  654. * Added blinking toolbar icon on new missing calls.
  655. * Added Web links in Help menu.
  656. *
  657. * Revision 1.32.2.21  2003/11/19 15:13:31  z_stoichev
  658. * Fixed proximity loop calls and missing Proximity Near
  659. * execution when a new phone is connected.
  660. * Fixed load database settings for new phone (do not
  661. * keep previous phone settings, but allow upgrade from
  662. * single phone database Fma version).
  663. * Fixed Auto-reconnect disables popup notifications.
  664. * Auto-reconnect and New message routines moved in
  665. * separated Timer, not using Pooling timer anymore.
  666. * New one is faster and will not blink toolbar buttons.
  667. *
  668. * Revision 1.32.2.20  2003/11/14 15:41:02  z_stoichev
  669. * Updates for patch 27d.
  670. *
  671. * Revision 1.32.2.19  2003/11/13 17:57:56  z_stoichev
  672. * Update to patch 27c.
  673. *
  674. * Revision 1.32.2.18  2003/11/12 16:58:39  z_stoichev
  675. * Add new icons and replace some old.
  676. * Proximity can run Screensaver now.
  677. * Proximity test implemented.
  678. * Phone can temporary disconnect if Headset clicked.
  679. * Download all messages on Text Messages Refresh.
  680. * Save database files on phonebook change.
  681. * Add voice call to sender from messages view.
  682. * Fixed volume and mute control.
  683. * Render SIM phonebook view on database load.
  684. *
  685. * Revision 1.32.2.17  2003/11/11 13:54:08  z_stoichev
  686. * Add personalization support.
  687. * Add text messages options: no popup, no baloon,
  688. * and move to archive.
  689. * Show progress on download all messages.
  690. * Add option for Show progress only if Restored.
  691. * Memeber sort mode when switching folders.
  692. * Fixed delete from group.
  693. * Don't delete SMS on phone when CNMI mode
  694. * 3 is used (forward messages only).
  695. * Refresh view when exit from Options.
  696. * Hide baloons on 3rd connect failure.
  697. * Volume control fixed.
  698. *
  699. * Revision 1.32.2.16  2003/11/10 16:24:59  z_stoichev
  700. * Fixed: changes are lost on re-connect.
  701. *
  702. * Revision 1.32.2.15  2003/11/10 14:03:10  z_stoichev
  703. * RC3
  704. *
  705. * Revision 1.32.2.14  2003/11/07 16:41:18  z_stoichev
  706. * Fixed phone clock zone missing issue (S55).
  707. * SIM phonebook view/editor recoded.
  708. *
  709. * Revision 1.32.2.13  2003/11/07 11:27:40  z_stoichev
  710. * Added common wizard image.
  711. * Replaced some toolbar images.
  712. * AddToGroup method created.
  713. * Connect on synchronization, if not
  714. * already connected.
  715. *
  716. * Revision 1.32.2.12  2003/11/06 16:33:12  z_stoichev
  717. * Action update state changed alot.
  718. * Abort action Esc hotkey removed.
  719. * Fixed Add to Group with non-english chars in
  720. * contact names.
  721. * Added HTML converter (+ XML ''' named
  722. * character support).
  723. * Added a Calls folder in Phone explorer (not finished
  724. * yet).
  725. * Added Select All action for phonebook entries.
  726. * Added Send message and Voice call to contacts
  727. * and phones into Explorer and default view windows.
  728. * Added Battery and Charging Algorithm support check.
  729. * Explorer Obex folder types auto-detection.
  730. * Obex file type auto-detection.
  731. * Don't say Connection Loss on user Abort.
  732. * New images added.
  733. * Bugfixes.
  734. *
  735. * Revision 1.32.2.11  2003/11/04 15:56:47  z_stoichev
  736. * FindPBbyName unicode support.
  737. * Update def explorer view on connect.
  738. * Don't show baloons on auto-connect.
  739. * Fix profiles toolbar left shift on folder click.
  740. * Obex folders type auto-detection.
  741. * Don't say Connection lost on Abort.
  742. * Add some debug messages.
  743. * Fixed typos.
  744. *
  745. * Revision 1.32.2.10  2003/10/31 15:02:15  z_stoichev
  746. * Ask for retry if Obex is already used by another app.
  747. * Load missed calls from phone.
  748. * Add headset button for incoming calls.
  749. *
  750. * Revision 1.32.2.9  2003/10/30 15:32:04  z_stoichev
  751. * Execute AT command semafor usage.
  752. * Get Operator error shown as "unknown operator".
  753. *
  754. * Revision 1.32.2.8  2003/10/30 13:31:57  z_stoichev
  755. * Fixed on connection steps are non-fatal.
  756. * Fixed execute phone command semafor usage.
  757. * Fixed minimize/restore on double-click when
  758. * Win+D, Win+M is pressed.
  759. * Fixed sending SMS to groups will select the
  760. * default number for any group memeber.
  761. * Fixed phone number positions cache update.
  762. * Abort works only if command is executing.
  763. *
  764. * Revision 1.32.2.7  2003/10/29 16:27:03  z_stoichev
  765. * SMS Status Report is detected from phone.
  766. * Fixed recoursive grouping name retrieval.
  767. * Fixed Groups loading is times faster (you
  768. * may have to refresh your phonebook, so the
  769. * phone positions are available).
  770. * Fixed Explorer update on contact change.
  771. * Fixed reload settings on restore issue.
  772. * Battery and Signal color scheme and font
  773. * are changed (by user request).
  774. * Added Send message to Group (not finished yet,
  775. * will select first contact number, which may
  776. * not be the proper one).
  777. * Added options for Startup loading of groups
  778. * and Folders (by user request).
  779. * Added options to disable Obex and IrmcSync
  780. * Thus disabling synchronization at all,
  781. * only full phonebook refresh is done.
  782. * Show Sent message to Name not to Number.
  783. *
  784. * Revision 1.32.2.6  2003/10/29 12:09:28  z_stoichev
  785. * Fixed recoursive grouping name retrieval.
  786. * Fixed Groups loading is times faster (you
  787. * may have to refresh your phonebook, so the
  788. * phone positions are available).
  789. * Fixed reload settings on restore issue.
  790. * Battery and Signal color scheme and font
  791. * are changed (by user request).
  792. *
  793. * Revision 1.32.2.5  2003/10/28 15:24:14  z_stoichev
  794. * Added new frame for default explorer view.
  795. *
  796. * Revision 1.32.2.4  2003/10/28 13:07:08  z_stoichev
  797. * Connect even if build contact structure fail
  798. * and use the default settings.
  799. * Fixed Groups mixed content/add to group.
  800. * Fixed clock synchronization error.
  801. * Clock sync is optional.
  802. * Changed battery est. time calculation.
  803. * Play connected sound on last connect step.
  804. * Always scroll Debug and Avtivity log to the
  805. * last line and remove empty last line.
  806. * Images changed.
  807. *
  808. * Revision 1.32.2.3  2003/10/27 17:08:12  z_stoichev
  809. * If folder Browsing fails, connect will continue without this feature.
  810. * Trying to sync phone clock will first try to connect if not connected.
  811. * Fixed auto-connect looping/messages.
  812. * On auto-connect failure show only debug information
  813. * message instead of error one.
  814. * Battery time left calculation tuned up.
  815. * When charging battery time left indicates time
  816. * until charge will complete. Show 'Done' when ready.
  817. * Separator line removed on profiles popup menu.
  818. * Check for stray OK is always called, even on errors.
  819. *
  820. * Revision 1.32.2.2  2003/10/27 09:50:55  z_stoichev
  821. * Prerelease bug-fixes.
  822. *
  823. * Revision 1.32.2.1  2003/10/27 07:22:54  z_stoichev
  824. * Build 0.1.0 RC1 Initial Checkin.
  825. *
  826. * Revision 1.32  2003/10/24 16:57:20  z_stoichev
  827. * Fixed "ATI phone" issue.
  828. *
  829. * Revision 1.31  2003/10/24 14:24:24  z_stoichev
  830. * Fixed errors on startup when the script file is missing.
  831. *
  832. * Revision 1.30  2003/10/24 13:04:00  z_stoichev
  833. * Added some new images.
  834. * Added profiles folder containing all phone profiles.
  835. * Diagram is cleared on connect.
  836. * Ask for item (contact, sms) deletion.
  837. * Fixed: "don't warn for SMS to archive" option was ignored.
  838. * Show baloon tooltip on profile change.
  839. * Preserve messages view and contacts view sort order.
  840. * Last empty line in debug log is removed.
  841. *
  842. * Revision 1.29  2003/10/22 13:25:35  z_stoichev
  843. * Make SMS to Archive warning optional.
  844. * Make progress indicator optional.
  845. * Show progress on Phonebook download.
  846. * Clerar some vars on destroy, and add some
  847. * checks on usage.
  848. * Make LoadOptions exceptions silent.
  849. *
  850. * Revision 1.28  2003/10/21 15:35:49  z_stoichev
  851. * Battery and Signal status border removed.
  852. * Code clean up.
  853. *
  854. * Revision 1.27  2003/10/21 13:46:15  z_stoichev
  855. * Show debug log only once on program startup.
  856. * Added "Show debug log" item in help menu if -debug
  857. * option is present.
  858. * Added "Fma on the web" link in Help menu.
  859. * New icons added in ImageList2.
  860. * Bug-fixes.
  861. *
  862. * Revision 1.26  2003/10/21 12:39:33  z_stoichev
  863. * Changed Obex Get method result value to cardinal.
  864. * Show baloon tooltip on new SMS message for 1 min.
  865. * Some display messages changed.
  866. *
  867. * Revision 1.25  2003/10/20 09:40:49  z_stoichev
  868. * Fixed some typo errors.
  869. * Minimize/restore animation bugfixes
  870. * and it's temporary disabled now.
  871. * Reverted to old tray area icons.
  872. *
  873. * Revision 1.24  2003/10/16 15:31:19  z_stoichev
  874. * Now diagram shows last 1 minute of statistics.
  875. * Charge is shown on battery's axe, because
  876. * they have similar values.
  877. * Battery and Signal indicators have new font color
  878. * and text labels, and they are read immediately on
  879. * startup, not waiting for timer trigger (first time only).
  880. *
  881. * Revision 1.23  2003/10/16 09:55:40  z_stoichev
  882. * Added CoolTrayIcon component reference.
  883. * Tray Icon is always visible, and appears after
  884. * Explorer crash, and with new icons (t610).
  885. * Minimize to tray area animation is added.
  886. * Baloon tooltip support with various info/error.
  887. * Missed calls shows baloon tooltip for 1 minute.
  888. * Explorer shows the phone model.
  889. * Bugfixes; some try-finally stats are included.
  890. *
  891. * Revision 1.22  2003/10/15 15:51:56  z_stoichev
  892. * Missed Calls Unicode support.
  893. * Missed Calls button is always visible until
  894. * the list of missed calls is cleared.
  895. * Added explorer folders for sounds, pics etc.
  896. * Post bookmark added to main menu.
  897. *
  898. * Revision 1.21  2003/10/15 11:11:21  z_stoichev
  899. * Fixed bug 823902: Move SMS from Archive to Phone/SIM.
  900. *
  901. * Revision 1.20  2003/10/14 15:05:10  z_stoichev
  902. * Fixed tray icon bug 672426.
  903. * OnShow routines moved to new method called StartupInitialize.
  904. * If Obex is not supported Phonebook refresh works without it.
  905. * Debug log is updated even if Debug window is closed (if start
  906. * minimized).
  907. *
  908. * Revision 1.19  2003/10/14 13:01:07  z_stoichev
  909. * Abort will not cancel future Obex sessions.
  910. * Unit SentSMS moved to uComposeSMS
  911. * which uses Address book etc.
  912. *
  913. * Revision 1.18  2003/10/14 10:26:14  z_stoichev
  914. * Fixed multiple Synchronization Log windows issue.
  915. * Synchronization Log is updated in realtime.
  916. * Unit SentSMS renamed to uComposeSMS.
  917. *
  918. * Revision 1.17  2003/10/14 08:14:31  z_stoichev
  919. * Fixed Monitoring activation on Options exit.
  920. * Sony Ericsson progress bar usage on connect.
  921. * Fixed pooling on disconnect/out of range.
  922. * Abort can interrupt connecting now.
  923. *
  924. * Revision 1.16  2003/10/13 14:19:38  z_stoichev
  925. * Modified to reflect changes in Obex methods.
  926. * Added is bookmark posting.
  927. * Posting note has a new field Class.
  928. * Connect to phone progress dialog.
  929. *
  930. * Revision 1.15  2003/10/10 13:26:54  z_stoichev
  931. * Phonebook refresh means sync.
  932. * Sync is faster, refresh only on changes.
  933. * Some icons remade.
  934. * Fix on disconnect when no device.
  935. *
  936. * Revision 1.14  2003/10/09 15:10:29  z_stoichev
  937. * Unicode support in tree vew explorer.
  938. * UTF-8 and UTF-7 support for vCard and Phonebook
  939. * entries (allow cyrillic etc. symbols).
  940. *
  941. * Revision 1.13  2003/10/09 10:17:10  z_stoichev
  942. * Trying to set UTF-8 or Latin-1 character sets
  943. * if they are supported by phone (in that order).
  944. * UTF-8 (cyrillic etc.) support for Profile names
  945. * using Latin-1 displays names as "???????".
  946. * Connection initialization on connect/disconnect
  947. * in order to reset changes made by previous
  948. * session (ATZ).
  949. *
  950. * Revision 1.12  2003/10/08 11:03:22  z_stoichev
  951. * New Message Indicator Mode detection and proper use.
  952. * Will not display error message on long operations as
  953. * entering a PIN code.
  954. * SIM status is retrieved and shown in status bar on connect
  955. * allowing Emergency Mode (not used yet) if SIM is absent.
  956. *
  957. * Revision 1.11  2003/08/31 07:26:48  bufflig
  958. * Added alternative export file dialogue to accomodate vCard export
  959. * of contacts, SaveDialog2.
  960. * Fixed minor bug regarding missed calls, stack variable was expected to keep
  961. * value between calls. Could make missed calls not beeing registered. Now
  962. * class variable is used instead.
  963. * Removed some unused variables etc, reducing warnings at compile time.
  964. *
  965. * Revision 1.10  2003/08/11 18:06:49  bufflig
  966. * Support for voice dialling on T300 series by using old fasioned
  967. * AT commands on phones that dont support AT*EVD and friends.
  968. * Also fixed bug 716685, the disappearing HangUp button.
  969. *
  970. * Revision 1.9  2003/07/18 12:27:48  bufflig
  971. * Added routine to flush a stray OK that SE T300/310 with software R3B sometimes
  972. * outputs after OBEX session is ended. Makes synchronize work on these phones.
  973. *
  974. * Revision 1.8  2003/07/02 12:32:01  crino77
  975. * RefreshPhoneBook for refresh after sync
  976. * statemonitor
  977. * x to minimize
  978. * fixed bug in call popup
  979. * All archive file must be in exe path
  980. * Unicode in profile
  981. * fixed bug in missed calls
  982. * added edit profile in Tool menu
  983. *
  984. * Revision 1.7  2003/02/26 13:27:25  crino77
  985. * Added winxp.res reference
  986. *
  987. * Revision 1.6  2003/02/17 06:56:51  crino77
  988. * Added support for missed calls
  989. *
  990. * Revision 1.5  2003/02/14 14:09:27  crino77
  991. * Modified SentMessage to get the MessRef
  992. * Modified procedure SendMessage for long sms support;
  993. * Added synclog button on toolbar and menurmes
  994. * Added sync button on toolbar and menu
  995. * Added AutoConnect feature in Form1.SHOW;
  996. * Added Sync Conflict storage
  997. * Added -DEBUGOBEX to debug Obex transaction
  998. * Bug "List out of bounds (16)" solved - HandleEBCA  add try/except on cycles times ;)
  999. * Added ActionExportSMS
  1000. * Added some public function:
  1001. *      - ObexGetObject(Path: Widestring): TStream;
  1002. *      - ObexPutObject(Path: Widestring; Stream: TStream): TStream;
  1003. * Added public procedure ObexDisconnect;
  1004. *
  1005. * Revision 1.4  2003/01/30 04:15:57  warren00
  1006. * Updated with header comments
  1007. *
  1008. *
  1009. *******************************************************************************
  1010. }
  1011.  
  1012. interface
  1013.  
  1014. {$R WinXP.res}
  1015.  
  1016. uses
  1017.   {$IFNDEF VER150}ThemeMgr, {$ENDIF}
  1018.   {$IFDEF VER150}XPStyleActnCtrls, {$ENDIF}
  1019.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  1020.   Dialogs, StdCtrls, ComCtrls, ExtCtrls, ToolWin, ActnList, Menus, ShellAPI,
  1021.   gsm_sms, ImgList, DateUtils, ActnMan, ActnCtrls,
  1022.   ActnMenus, AppEvnts, StdActns, Placemnt, Registry, WinSock, IniFiles,
  1023.   Buttons, TntStdCtrls, VirtualTrees, uObex, uExploreView, uWaitComplete,
  1024.   LMDCustomComponent, LMDOneInstance, LMDControl, LMDBaseControl,
  1025.   LMDBaseGraphicControl, LMDGraphicControl, LMDBaseMeter,
  1026.   LMDCustomProgressFill, LMDProgressFill, LMDHookComponent, LMDFMDrop,
  1027.   WSocket, WBluetoothSocket, WIrCOMMSocket, mmsystem, uAccessoriesMenu,
  1028.   uSIMEdit, uMsgView, uSyncPhonebook, uVCard, uInfoView, 
  1029.   uMissedCalls, uKeyPad, TntComCtrls, CoolTrayIcon, WebUtil, jpeg, AMixer,
  1030.   LMDFill, WebUpdate, aw_SCtrl, CPort, uScriptEditor, uDebug, uSyncLog, uActivityLog,
  1031.   uContactSync, uChatSMS, GR32_Image;
  1032.  
  1033. const
  1034.   __fma_objcall = 'FmaInternalObjectCall';
  1035.  
  1036. const
  1037.   FMA_HANDLEMESSAGE = WM_USER + 100;
  1038.  
  1039. type
  1040.   TConfirmation = (cfNone, cfYesToAll, cfNoToAll);
  1041.  
  1042.   TFmaHandleMessage = record
  1043.     Msg: Cardinal;
  1044.     Message: PChar;
  1045.     Length: Longint;
  1046.     Result: Longint;
  1047.   end;
  1048.  
  1049.   TStartupOptions = record
  1050.     NoObex,NoIRMC,NoGroups,NoFolders,NoProfiles,NoCalls,NoBookmarks: boolean;
  1051.   end;
  1052.   TProximityOptions = record
  1053.     AwayLock,NearUnlock,RunSS: boolean;
  1054.     AwayMusicMode,NearMusicMode: integer;
  1055.   end;
  1056.   TTextMessageOptions = record
  1057.     NoPopup,NoBaloon,MoveToArchive,FullWarning: boolean;
  1058.   end;
  1059.  
  1060.   TForm1 = class(TForm)
  1061.     StatusBar: TStatusBar;
  1062.     CoolBar: TCoolBar;
  1063.     ActionList1: TActionList;
  1064.     ActionConnectionConnect: TAction;
  1065.     ActionConnectionDisconnect: TAction;
  1066.     ImageList1: TImageList;
  1067.     ActionContactsDownload: TAction;
  1068.     Splitter1: TSplitter;
  1069.     PopupMenu1: TPopupMenu;
  1070.     Refresh3: TMenuItem;
  1071.     ActionConnectionDownload: TAction;
  1072.     ActionSMSArchiveMsg: TAction;
  1073.     ActionSelectAll: TAction;
  1074.     ActionDelete: TAction;
  1075.     ActionSMSMoveMsgToArchive: TAction;
  1076.     ActionSMSNewMsg: TAction;
  1077.     ActionContactsNewMsg: TAction;
  1078.     NewMessage2: TMenuItem;
  1079.     ActionSMSReplyMsg: TAction;
  1080.     ActionSMSForwardMsg: TAction;
  1081.     ActionConnectionToggle: TAction;
  1082.     ActionContactsVoiceCall: TAction;
  1083.     Call1: TMenuItem;
  1084.     Timer1: TTimer;
  1085.     ApplicationEvents1: TApplicationEvents;
  1086.     trayMenu: TPopupMenu;
  1087.     Connect1: TMenuItem;
  1088.     N1: TMenuItem;
  1089.     NewMessage1: TMenuItem;
  1090.     MainMenu1: TMainMenu;
  1091.     Connection1: TMenuItem;
  1092.     Connect2: TMenuItem;
  1093.     Disconnect1: TMenuItem;
  1094.     Refresh1: TMenuItem;
  1095.     N5: TMenuItem;
  1096.     Exit1: TMenuItem;
  1097.     Action2: TMenuItem;
  1098.     MessagetoContact1: TMenuItem;
  1099.     NewMessage3: TMenuItem;
  1100.     Reply2: TMenuItem;
  1101.     Forward2: TMenuItem;
  1102.     N7: TMenuItem;
  1103.     Delete2: TMenuItem;
  1104.     N8: TMenuItem;
  1105.     CopytoArchive1: TMenuItem;
  1106.     MovetoArchive2: TMenuItem;
  1107.     N9: TMenuItem;
  1108.     Call2: TMenuItem;
  1109.     SelectAll1: TMenuItem;
  1110.     Help1: TMenuItem;
  1111.     About1: TMenuItem;
  1112.     ImageList2: TImageList;
  1113.     ActionAbout: TAction;
  1114.     ActionWindowRestore: TAction;
  1115.     ShowRestore1: TMenuItem;
  1116.     Exit2: TMenuItem;
  1117.     FormStorage1: TFormStorage;
  1118.     ActionToolsOptions: TAction;
  1119.     Tools1: TMenuItem;
  1120.     Options1: TMenuItem;
  1121.     ActionConnectionMonitor: TAction;
  1122.     Monitor1: TMenuItem;
  1123.     ActionConnectionAutoConnect: TAction;
  1124.     AutoConnect1: TMenuItem;
  1125.     ToolBar1: TToolBar;
  1126.     ToolButton1: TToolButton;
  1127.     ToolButton2: TToolButton;
  1128.     RefreshToolButton: TToolButton;
  1129.     ScriptControl: TawScriptControl;
  1130.     ActionToolsEditScript: TAction;
  1131.     EditScript1: TMenuItem;
  1132.     OpenDialog1: TOpenDialog;
  1133.     ActionConnectionAbort: TAction;
  1134.     N16: TMenuItem;
  1135.     Abort1: TMenuItem;
  1136.     ActionToolsUpload: TAction;
  1137.     Upload1: TMenuItem;
  1138.     N17: TMenuItem;
  1139.     ToolButton13: TToolButton;
  1140.     ActionToolsPostNote: TAction;
  1141.     Postanote1: TMenuItem;
  1142.     LMDOneInstance1: TLMDOneInstance;
  1143.     LMDFMDrop: TLMDFMDrop;
  1144.     ToolBar2: TToolBar;
  1145.     cbProfile: TTntComboBox;
  1146.     ToolButton11: TToolButton;
  1147.     ActionSMSDownloadInbox: TAction;
  1148.     ActionToolsEditProfile: TAction;
  1149.     WBtSocket: TWBluetoothSocket;
  1150.     WIrSocket: TWIrCOMMSocket;
  1151.     ActionSMSExport: TAction;
  1152.     N3: TMenuItem;
  1153.     ExportSMS1: TMenuItem;
  1154.     SaveDialog1: TSaveDialog;
  1155.     ToolButton14: TToolButton;
  1156.     ActionSyncPhonebook: TAction;
  1157.     StartSyncPhoneBook1: TMenuItem;
  1158.     Sync1: TMenuItem;
  1159.     ActionSyncLog: TAction;
  1160.     ActionSyncLog1: TMenuItem;
  1161.     ToolButton16: TToolButton;
  1162.     ActionMissedCalls: TAction;
  1163.     ActionMissedCalls1: TMenuItem;
  1164.     ActionKeyPad: TAction;
  1165.     KeyPad1: TMenuItem;
  1166.     ActionExit: TAction;
  1167.     ActionContactsExportME: TAction;
  1168.     ExportContacts1: TMenuItem;
  1169.     ActionToolsEditProfile1: TMenuItem;
  1170.     SaveDialog2: TSaveDialog;
  1171.     ActionToolsPostBookmark: TAction;
  1172.     Postbookmark1: TMenuItem;
  1173.     CoolTrayIcon1: TCoolTrayIcon;
  1174.     ImageList3: TImageList;
  1175.     ActionWindowMinimize: TAction;
  1176.     FmaOnSFNet1: TMenuItem;
  1177.     N18: TMenuItem;
  1178.     Showdebuglog1: TMenuItem;
  1179.     ActionToolsChangeProfile: TAction;
  1180.     ActivateProfile1: TMenuItem;
  1181.     EditProfile1: TMenuItem;
  1182.     ActionToolsDownload: TAction;
  1183.     ObexSaveDialog: TSaveDialog;
  1184.     N19: TMenuItem;
  1185.     Download2: TMenuItem;
  1186.     PanelExplorer: TPanel;
  1187.     PanelFolders: TPanel;
  1188.     Explorer: TTntTreeView;
  1189.     SpeedButton1: TSpeedButton;
  1190.     ViewExplorer1: TMenuItem;
  1191.     ActionConnectionExplorer: TAction;
  1192.     SyncPhoneClock1: TMenuItem;
  1193.     ActionExplorerUpFolder: TAction;
  1194.     ToolButton20: TToolButton;
  1195.     ActionContactsNewPerson: TAction;
  1196.     N21: TMenuItem;
  1197.     newcontact1: TMenuItem;
  1198.     Properties1: TMenuItem;
  1199.     ToolButton23: TToolButton;
  1200.     ToolBar3: TToolBar;
  1201.     ToolButton5: TToolButton;
  1202.     ToolButton6: TToolButton;
  1203.     ToolButton7: TToolButton;
  1204.     ToolButton8: TToolButton;
  1205.     ToolButton29: TToolButton;
  1206.     ToolButton30: TToolButton;
  1207.     ToolBar4: TToolBar;
  1208.     ToolButton17: TToolButton;
  1209.     ToolButton10: TToolButton;
  1210.     btnUpload: TToolButton;
  1211.     btnDownload: TToolButton;
  1212.     ToolButton26: TToolButton;
  1213.     ToolButton9: TToolButton;
  1214.     ToolButton12: TToolButton;
  1215.     ToolButton18: TToolButton;
  1216.     ActionEditGoUp: TAction;
  1217.     ActionEditGoDown: TAction;
  1218.     ToolButton19: TToolButton;
  1219.     FramePanel: TPanel;
  1220.     PanelTest: TPanel;
  1221.     TntPageControl1: TTntPageControl;
  1222.     TntTabSheet2: TTntTabSheet;
  1223.     Memo3: TMemo;
  1224.     Button3: TButton;
  1225.     cbTerminal: TTntComboBox;
  1226.     TntTabSheet1: TTntTabSheet;
  1227.     Label1: TLabel;
  1228.     Image: TImage;
  1229.     Label4: TLabel;
  1230.     Label5: TLabel;
  1231.     Memo2: TMemo;
  1232.     Memo1: TMemo;
  1233.     Button1: TButton;
  1234.     Button2: TButton;
  1235.     Edit2: TEdit;
  1236.     RadioButton1: TRadioButton;
  1237.     RadioButton2: TRadioButton;
  1238.     cbObex: TComboBox;
  1239.     Button10: TButton;
  1240.     Button11: TButton;
  1241.     TntTabSheet3: TTntTabSheet;
  1242.     Label2: TLabel;
  1243.     Label3: TLabel;
  1244.     TntEdit1: TTntEdit;
  1245.     TntEdit2: TTntEdit;
  1246.     Button4: TButton;
  1247.     Button5: TButton;
  1248.     Button6: TButton;
  1249.     Button7: TButton;
  1250.     Button8: TButton;
  1251.     Button9: TButton;
  1252.     Button12: TButton;
  1253.     DescrPanel: TPanel;
  1254.     Panel1: TPanel;
  1255.     ToolButton21: TToolButton;
  1256.     AudioMixer1: TAudioMixer;
  1257.     lblCurrentPage: TTntLabel;
  1258.     notenew1: TMenuItem;
  1259.     bookmarknew1: TMenuItem;
  1260.     PopupMenu2: TPopupMenu;
  1261.     ShowExplorer1: TMenuItem;
  1262.     N14: TMenuItem;
  1263.     N15: TMenuItem;
  1264.     ImageList4: TImageList;
  1265.     LMDFill1: TLMDFill;
  1266.     View1: TMenuItem;
  1267.     MsgPreview1: TMenuItem;
  1268.     ActionViewMsgPreview: TAction;
  1269.     ToolButton22: TToolButton;
  1270.     ToolButton24: TToolButton;
  1271.     Timer2: TTimer;
  1272.     FmaOnTheWeb1: TMenuItem;
  1273.     FmaOnTheWeb2: TMenuItem;
  1274.     ActionContactsAddContact: TAction;
  1275.     EditOwnCard1: TMenuItem;
  1276.     ActionContactsOwn: TAction;
  1277.     N6: TMenuItem;
  1278.     SyncOutlook1: TMenuItem;
  1279.     SyncBookmarks1: TMenuItem;
  1280.     N13: TMenuItem;
  1281.     FmaOnForums1: TMenuItem;
  1282.     N22: TMenuItem;
  1283.     CheckforUpdate1: TMenuItem;
  1284.     N25: TMenuItem;
  1285.     N26: TMenuItem;
  1286.     SendOutboxMessages1: TMenuItem;
  1287.     ToolButton3: TToolButton;
  1288.     ToolButton25: TToolButton;
  1289.     ActionConnectionSendOutboxMsgs: TAction;
  1290.     ActionToolsKeybLock: TAction;
  1291.     ToolButton27: TToolButton;
  1292.     ToggleKeyboardLock1: TMenuItem;
  1293.     LMDFill2: TLMDFill;
  1294.     pbRSSI: TLMDProgressFill;
  1295.     pbPower: TLMDProgressFill;
  1296.     Label6: TLabel;
  1297.     ActionSMSImport: TAction;
  1298.     ActionContactsImportME: TAction;
  1299.     Export1: TMenuItem;
  1300.     Import1: TMenuItem;
  1301.     ImportSMS1: TMenuItem;
  1302.     ImportContacts1: TMenuItem;
  1303.     N27: TMenuItem;
  1304.     AllRestorePhone1: TMenuItem;
  1305.     N28: TMenuItem;
  1306.     AllBackupPhone1: TMenuItem;
  1307.     DebugTools1: TMenuItem;
  1308.     Timer3: TTimer;
  1309.     FmaWebUpdate1: TFmaWebUpdate;
  1310.     ActionSyncWithOutlook: TAction;
  1311.     N29: TMenuItem;
  1312.     swprofile1: TMenuItem;
  1313.     ActionSwitchUserProfile: TAction;
  1314.     ToolButton15: TToolButton;
  1315.     ToolButton28: TToolButton;
  1316.     lblCurrentPageDtls: TLabel;
  1317.     activitylog1: TMenuItem;
  1318.     ActionViewActivityLog: TAction;
  1319.     ComPort: TComPort;
  1320.     ToolBar5: TToolBar;
  1321.     ToolButton36: TToolButton;
  1322.     ToolButton4: TToolButton;
  1323.     EditCut1: TEditCut;
  1324.     EditCopy1: TEditCopy;
  1325.     EditPaste1: TEditPaste;
  1326.     EditUndo1: TEditUndo;
  1327.     ActionDebugLog: TAction;
  1328.     ShowCaption1: TMenuItem;
  1329.     ShowDiagram1: TMenuItem;
  1330.     ActionContactsExportSM: TAction;
  1331.     ActionContactsExport: TAction;
  1332.     ActionContactsImportSM: TAction;
  1333.     ActionContactsImport: TAction;
  1334.     ActionContactsNewChat: TAction;
  1335.     ToolButton31: TToolButton;
  1336.     ChatContact1: TMenuItem;
  1337.     ChatContact2: TMenuItem;
  1338.     N30: TMenuItem;
  1339.     N11: TMenuItem;
  1340.     ActionToolsWapHomepage: TAction;
  1341.     EditWapHomePage1: TMenuItem;
  1342.     EditWapHomePage2: TMenuItem;
  1343.     EditFavorites1: TMenuItem;
  1344.     Edit1: TMenuItem;
  1345.     N20: TMenuItem;
  1346.     N23: TMenuItem;
  1347.     N10: TMenuItem;
  1348.     EditCallFavorites1: TMenuItem;
  1349.     ToolButton32: TToolButton;
  1350.     ActionContactsVoiceHangup: TAction;
  1351.     N12: TMenuItem;
  1352.     Cut1: TMenuItem;
  1353.     Copy1: TMenuItem;
  1354.     Paste1: TMenuItem;
  1355.     Undo1: TMenuItem;
  1356.     ToolButton33: TToolButton;
  1357.     ActionToolsCreateGroup: TAction;
  1358.     NewGroup1: TMenuItem;
  1359.     NewGroup2: TMenuItem;
  1360.     CommonBitmaps: TBitmap32List;
  1361.     ActionToolsSilent: TAction;
  1362.     ToolButton34: TToolButton;
  1363.     EnableSilentMode1: TMenuItem;
  1364.     N2: TMenuItem;
  1365.     N4: TMenuItem;
  1366.     PowerOffPhone1: TMenuItem;
  1367.     ActionToolsPowerOff: TAction;
  1368.     procedure ActionConnectionConnectExecute(Sender: TObject);
  1369.     procedure ActionConnectionDisconnectExecute(Sender: TObject);
  1370.     procedure ActionConnectionDownloadExecute(Sender: TObject);
  1371.     procedure ActionContactsDownloadExecute(Sender: TObject);
  1372.     procedure ActionConnectionToggleExecute(Sender: TObject);
  1373.     procedure ActionContactsVoiceCallExecute(Sender: TObject);
  1374.     procedure ActionConnectionMonitorExecute(Sender: TObject);
  1375.     procedure ActionConnectionAutoConnectExecute(Sender: TObject);
  1376.     procedure ActionSMSDownloadInboxExecute(Sender: TObject);
  1377.     procedure ActionSMSArchiveMsgExecute(Sender: TObject);
  1378.     procedure ActionSelectAllExecute(Sender: TObject);
  1379.     procedure ActionDeleteExecute(Sender: TObject);
  1380.     procedure ActionSMSMoveMsgToArchiveExecute(Sender: TObject);
  1381.     procedure ActionSMSNewMsgExecute(Sender: TObject);
  1382.     procedure ActionSMSReplyMsgExecute(Sender: TObject);
  1383.     procedure ActionSMSForwardMsgExecute(Sender: TObject);
  1384.     procedure ActionAboutExecute(Sender: TObject);
  1385.     procedure ActionWindowRestoreExecute(Sender: TObject);
  1386.     procedure ActionToolsOptionsExecute(Sender: TObject);
  1387.  
  1388.     procedure ExplorerGetSelectedIndex(Sender: TObject; Node: TTreeNode);
  1389.     procedure ExplorerChange(Sender: TObject; Node: TTreeNode);
  1390.     procedure FormCreate(Sender: TObject);
  1391.     procedure FormDestroy(Sender: TObject);
  1392.     procedure FormClose(Sender: TObject; var Action: TCloseAction);
  1393.     procedure ContactListGetSelectedIndex(Sender: TObject;
  1394.       Node: TTreeNode);
  1395.     procedure ComPortAfterOpen(Sender: TObject);
  1396.     procedure ComPortAfterClose(Sender: TObject);
  1397.     procedure ComPortRxChar(Sender: TObject; Count: Integer);
  1398.     procedure ActionContactsNewMsgExecute(Sender: TObject);
  1399.     procedure Timer1Timer(Sender: TObject);
  1400.     procedure ApplicationEvents1Minimize(Sender: TObject);
  1401.     procedure ApplicationEvents1Restore(Sender: TObject);
  1402.     procedure ScriptControlError(Sender: TObject;
  1403.       Error: TawScriptError);
  1404.     procedure ActionToolsEditScriptExecute(Sender: TObject);
  1405.     procedure ActionConnectionAbortExecute(Sender: TObject);
  1406.     procedure ActionToolsUploadExecute(Sender: TObject);
  1407.     procedure ActionToolsPostNoteExecute(Sender: TObject);
  1408.     procedure cbProfileChange(Sender: TObject);
  1409.     procedure ExplorerDblClick(Sender: TObject);
  1410.     procedure StatusBarDrawPanel(StatusBar: TStatusBar;
  1411.       Panel: TStatusPanel; const Rect: TRect);
  1412.     procedure LMDFMDropFMDragDrop(Sender: TObject; fcount, x, y: Integer;
  1413.       FileList: TStrings);
  1414.     procedure WSocketOnSessionConnect(Sender: TObject; Error: Word);
  1415.     procedure WSocketOnSessionClosed(Sender: TObject; Error: Word);
  1416.     procedure WBtSocketDataAvailable(Sender: TObject; Error: Word);
  1417.     procedure WBtSocketChangeState(Sender: TObject; OldState,
  1418.       NewState: TSocketState);
  1419.     procedure Button1Click(Sender: TObject);
  1420.     procedure Button2Click(Sender: TObject);
  1421.     procedure ActionSMSExportExecute(Sender: TObject);
  1422.     procedure ActionSyncPhonebookExecute(Sender: TObject);
  1423.     procedure ActionSyncLogExecute(Sender: TObject);
  1424.     procedure ActionMissedCallsExecute(Sender: TObject);
  1425.     procedure ActionKeyPadExecute(Sender: TObject);
  1426.     procedure ActionExitExecute(Sender: TObject);
  1427.     procedure ActionContactsExportMEExecute(Sender: TObject);
  1428.     procedure ActionToolsPostBookmarkExecute(Sender: TObject);
  1429.     procedure ActionObexReadyUpdate(Sender: TObject);
  1430.     procedure ActionToolsEditProfileUpdate(Sender: TObject);
  1431.     procedure ActionConnectionConnectUpdate(Sender: TObject);
  1432.     procedure ActionConnectionDisconnectUpdate(Sender: TObject);
  1433.     procedure ActionConnectionToggleUpdate(Sender: TObject);
  1434.     procedure ActionMissedCallsUpdate(Sender: TObject);
  1435.     procedure ActionWindowMinimizeExecute(Sender: TObject);
  1436.     procedure FmaOnTheWeb1Click(Sender: TObject);
  1437.     procedure ActionToolsChangeProfileExecute(Sender: TObject);
  1438.     procedure ActionToolsChangeProfileUpdate(Sender: TObject);
  1439.     procedure Button3Click(Sender: TObject);
  1440.     procedure Button4Click(Sender: TObject);
  1441.     procedure Button5Click(Sender: TObject);
  1442.     procedure Button6Click(Sender: TObject);
  1443.     procedure Button7Click(Sender: TObject);
  1444.     procedure Button8Click(Sender: TObject);
  1445.     procedure Button9Click(Sender: TObject);
  1446.     procedure Button10Click(Sender: TObject);
  1447.     procedure Button11Click(Sender: TObject);
  1448.     procedure ActionToolsDownloadUpdate(Sender: TObject);
  1449.     procedure ActionToolsDownloadExecute(Sender: TObject);
  1450.     procedure SpeedButton1Click(Sender: TObject);
  1451.     procedure ActionConnectionExplorerUpdate(Sender: TObject);
  1452.     procedure ActionConnectionExplorerExecute(Sender: TObject);
  1453.     procedure SyncPhoneClock1Click(Sender: TObject);
  1454.     procedure ActionExplorerUpFolderUpdate(Sender: TObject);
  1455.     procedure ActionExplorerUpFolderExecute(Sender: TObject);
  1456.     procedure trayMenuPopup(Sender: TObject);
  1457.     procedure CoolTrayIcon1DblClick(Sender: TObject);
  1458.     procedure ActionBusyUpdate(Sender: TObject);
  1459.     procedure ActionEditCommonUpdate(Sender: TObject);
  1460.     procedure Button12Click(Sender: TObject);
  1461.     procedure ActionContactsNewPersonUpdate(Sender: TObject);
  1462.     procedure ActionContactsNewPersonExecute(Sender: TObject);
  1463.     procedure ActionContactsVoiceCallUpdate(Sender: TObject);
  1464.     procedure ActionContactsNewMsgUpdate(Sender: TObject);
  1465.     procedure ActionSMSUpdate(Sender: TObject);
  1466.     procedure ActionContactsExportMEUpdate(Sender: TObject);
  1467.     procedure ExplorerContextPopup(Sender: TObject; MousePos: TPoint;
  1468.       var Handled: Boolean);
  1469.     procedure ActionEditGoUpUpdate(Sender: TObject);
  1470.     procedure ActionEditGoUpExecute(Sender: TObject);
  1471.     procedure ActionEditGoDownUpdate(Sender: TObject);
  1472.     procedure ActionEditGoDownExecute(Sender: TObject);
  1473.     procedure ActionSMSArchiveMsgUpdate(Sender: TObject);
  1474.     procedure ActionConnectionDownloadUpdate(Sender: TObject);
  1475.     procedure Properties1Click(Sender: TObject);
  1476.     procedure PopupMenu1Popup(Sender: TObject);
  1477.     procedure ShowExplorer1Click(Sender: TObject);
  1478.     procedure ActionViewMsgPreviewUpdate(Sender: TObject);
  1479.     procedure ActionViewMsgPreviewExecute(Sender: TObject);
  1480.     procedure Timer2Timer(Sender: TObject);
  1481.     procedure FmaOnSFNet1Click(Sender: TObject);
  1482.     procedure ActionContactsAddContactUpdate(Sender: TObject);
  1483.     procedure ActionContactsAddContactExecute(Sender: TObject);
  1484.     procedure ActionContactsOwnExecute(Sender: TObject);
  1485.     procedure ExplorerCustomDrawItem(Sender: TCustomTreeView;
  1486.       Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
  1487.     procedure ActionIsConnUpdate(Sender: TObject);
  1488.     procedure FmaOnForums1Click(Sender: TObject);
  1489.     //procedure CheckforUpdate1Click(Sender: TObject);
  1490.     procedure ActionConnectionSendOutboxMsgsExecute(Sender: TObject);
  1491.     procedure ActionConnectionSendOutboxMsgsUpdate(Sender: TObject);
  1492.     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  1493.     procedure ActionToolsKeybLockUpdate(Sender: TObject);
  1494.     procedure ActionToolsKeybLockExecute(Sender: TObject);
  1495.     procedure cbTerminalEnter(Sender: TObject);
  1496.     procedure cbTerminalExit(Sender: TObject);
  1497.     procedure ActionSMSImportUpdate(Sender: TObject);
  1498.     procedure ActionSMSImportExecute(Sender: TObject);
  1499.     procedure ActionContactsImportMEUpdate(Sender: TObject);
  1500.     procedure ActionContactsImportMEExecute(Sender: TObject);
  1501.     procedure DebugTools1Click(Sender: TObject);
  1502.     procedure ScriptControlCallFunction(Sender: TObject;
  1503.       const FunctionName: String; const Params: array of Variant);
  1504.     procedure Timer3Timer(Sender: TObject);
  1505.     procedure ActionSyncWithOutlookExecute(Sender: TObject);
  1506.     procedure ActionSyncWithOutlookUpdate(Sender: TObject);
  1507.     procedure FmaWebUpdate1BeforeUpdate(Sender: TObject;
  1508.       var AllowRestart: Boolean);
  1509.     procedure FmaWebUpdate1Error(Sender: TObject; Message: String);
  1510.     procedure CheckforUpdate2Click(Sender: TObject);
  1511.     procedure ActionSwitchUserProfileUpdate(Sender: TObject);
  1512.     procedure ActionSwitchUserProfileExecute(Sender: TObject);
  1513.     procedure ToolButton15Click(Sender: TObject);
  1514.     procedure CoolTrayIcon1BalloonHintClick(Sender: TObject);
  1515.     procedure ActionViewActivityLogUpdate(Sender: TObject);
  1516.     procedure ActionViewActivityLogExecute(Sender: TObject);
  1517.     procedure ToolBar5CustomDrawButton(Sender: TToolBar;
  1518.       Button: TToolButton; State: TCustomDrawState;
  1519.       var DefaultDraw: Boolean);
  1520.     procedure ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);
  1521.     procedure ActionSyncLogUpdate(Sender: TObject);
  1522.     procedure ActionDebugLogUpdate(Sender: TObject);
  1523.     procedure ActionDebugLogExecute(Sender: TObject);
  1524.     procedure PopupMenu2Popup(Sender: TObject);
  1525.     procedure ShowCaption1Click(Sender: TObject);
  1526.     procedure ShowDiagram1Click(Sender: TObject);
  1527.     procedure ActionContactsExportSMUpdate(Sender: TObject);
  1528.     procedure ActionContactsExportSMExecute(Sender: TObject);
  1529.     procedure ActionContactsExportUpdate(Sender: TObject);
  1530.     procedure ActionContactsExportExecute(Sender: TObject);
  1531.     procedure ActionContactsImportSMUpdate(Sender: TObject);
  1532.     procedure ActionContactsImportSMExecute(Sender: TObject);
  1533.     procedure ActionContactsImportUpdate(Sender: TObject);
  1534.     procedure ActionContactsImportExecute(Sender: TObject);
  1535.     procedure ActionContactsNewChatUpdate(Sender: TObject);
  1536.     procedure ActionContactsNewChatExecute(Sender: TObject);
  1537.     procedure ActionToolsWapHomepageUpdate(Sender: TObject);
  1538.     procedure ActionToolsWapHomepageExecute(Sender: TObject);
  1539.     procedure EditFavorites1Click(Sender: TObject);
  1540.     procedure EditCallFavorites1Click(Sender: TObject);
  1541.     procedure ActionContactsVoiceHangupUpdate(Sender: TObject);
  1542.     procedure ActionContactsVoiceHangupExecute(Sender: TObject);
  1543.     procedure ApplicationEvents1Hint(Sender: TObject);
  1544.     procedure ActionToolsCreateGroupExecute(Sender: TObject);
  1545.     procedure SyncBookmarks1Click(Sender: TObject);
  1546.     procedure ActionToolsPostBookmarkUpdate(Sender: TObject);
  1547.     procedure ActionToolsSilentUpdate(Sender: TObject);
  1548.     procedure ActionToolsSilentExecute(Sender: TObject);
  1549.     procedure ActionToolsPowerOffExecute(Sender: TObject);
  1550.   private
  1551.     { Private declarations }
  1552.     FLastMenuButton: TToolButton;
  1553.     ChartShiftCnt, FKeyMSec: Cardinal;
  1554.  
  1555.     FBTAddress: String;
  1556.     FBtPort: String;
  1557.  
  1558.     FConnectionError,FProximityActive,FLastReconnect,FTemporaryOffline,FAutoProfile,
  1559.     FDoNotRefreshViewOnConnect,FHaveVoiceDialCommand_Answer, FHaveVoiceDialCommand_Dial, FHaveVoiceDialCommand_Hangup,FDatabaseLoaded: Boolean;
  1560.  
  1561.     FMessage,FLastBaloonMessagePDU: String;
  1562.  
  1563.     FNewMessageList: TStrings;
  1564.     FLookupList: TStrings;
  1565.  
  1566.     FNotFirstInstance,
  1567.     FKeyState,FKeyMonitoring,FKeybLocked,FSilentMode,FEBCAKeyMonStopped: Boolean;
  1568.  
  1569.     FScriptFile: String;
  1570.  
  1571.     //FCurrentInterval: Integer;
  1572.     EBCALastState: Integer;
  1573.  
  1574.     FAlphaCall : Integer;
  1575.     FAlphaDebug : Integer;
  1576.     FAlphaMessage : Integer;
  1577.     FAlphaCompose : Integer;
  1578.  
  1579.     FAccessoriesMenu: TAccessoriesMenu;
  1580.     FCallM: boolean;
  1581.     FMsgM: boolean;
  1582.     FStateMonitor,FDoSyncClock: boolean;
  1583.     FExit,FExiting,FExitWindows: Boolean;
  1584.     FMinimize,FCheckOutbox: Boolean;
  1585.     FLastECAVStatus: Integer;
  1586.     FLastShownFrame,FLastClockTZ: string;
  1587.     procedure ReleaseMainMenuButton;
  1588.  
  1589.     procedure DoRemoveGroupMemberOrFile;
  1590.     procedure DoRemoveBookmark;
  1591.     procedure DoRemoveGroup;
  1592.  
  1593.     // for selected explorer item
  1594.     procedure DownloadSMS(msgType: Integer; Node: TtntTreeNode = nil); overload;
  1595.     procedure DownloadSMS(msgType: Integer; memLocation: String; Node: TtntTreeNode = nil); overload;
  1596.     // into custom location (tstrings)
  1597.     procedure DownloadSMS(msgType: Integer; var sl: TStrings); overload;
  1598.     procedure DownloadSMS(msgType: Integer; memLocation: String; var sl: TStrings); overload;
  1599.     // for new messages
  1600.     procedure DownloadSMS(memLocation: String; index: Integer); overload;
  1601.     // other
  1602.     procedure FlushOK;
  1603.  
  1604.     procedure HandleCPMS(AMsg: String);
  1605.     procedure HandleECAV(AMsg: String);
  1606.     procedure HandleCOPS(AMsg: String);
  1607.     procedure HandleCKEV(AMsg: String);
  1608.     procedure HandleCIEV(AMsg: String);
  1609.     procedure HandleCSCS(AMsg: String);
  1610.     procedure HandleCCLK(AMsg: String);
  1611.     procedure HandleCPIN(AMsg: String);
  1612.     procedure HandleCNMI(AMsg: String);
  1613.     procedure HandleEMIV(AMsg: String);
  1614.     procedure HandleEAMI(AMsg: String);
  1615.     procedure HandleEBCA(AMsg: String);
  1616.     procedure HandleCLCK(AMsg: String);
  1617.     procedure HandleStatus(AMsg: String);
  1618.     procedure HandleNewSMS(AMsg: String);
  1619.     procedure LoadOptions;
  1620.     procedure ParsePhonebookList(var sl: TStrings);
  1621.     procedure ParsePhonebookListFromSync(var sl: TStrings);      // SIM View only
  1622.     procedure ParsePhonebookListFromEditor(ANode: TtntTreeNode); // SIM View only
  1623.     procedure SetPanelText(id: Integer; str: String = '');
  1624. //    procedure WaitComplete;
  1625.     function LoadScript: boolean;
  1626.     procedure ScriptEvent(const FunctionName: string; const Params: array of Variant);
  1627.     procedure ScheduleScriptEvent(const FunctionName: string; const Params: array of Variant);
  1628.     procedure EBCAState(Enable: Boolean; KeyMonToo: Boolean = True);
  1629.     procedure ClearBuffer;
  1630.     procedure SetFrameVisible(name: String; visible: Boolean = True);
  1631.     procedure GetContactRestrict;
  1632.     procedure ObexListFolder(Path: WideString; var Dir: TStringList; Connect: boolean = true);
  1633.     function ObexFolderPath(Node: TtntTreeNode): WideString;
  1634.     procedure PharseObexDir(Node: TtntTreeNode; Dir: TStringList);
  1635.     procedure CalculateTimeLeft(Model,Charge: string; Position, Max: integer);
  1636.     procedure UpdateMessagePreview;
  1637.     procedure AddCall(Node: TtntTreeNode; contact: WideString; time: string; AsFirst: boolean = false);
  1638.     procedure ReindexCallsNode(Node: TTntTreeNode);
  1639.     procedure DoLog(Form: TfrmDebug; str: String; PrefixTimestamp: boolean = True);
  1640.     procedure SyncContactsConflict(Sender: TObject; Contact: TContact;
  1641.       const Description: WideString; const Item0Name, Item1Name: String;
  1642.       var SelectedItem: Integer);
  1643.     procedure SyncContactsFirstTime(Sender: TObject; var Continue: Boolean);
  1644.     procedure SyncContactsError(Sender: TObject; const Message: String);
  1645.     procedure SyncContactsConfirm(Sender: TObject; Contact: TContact; Action: TContactAction;
  1646.       const Description: WideString; var Confirmed: Boolean);
  1647.     procedure SyncContactsChooseLink(Sender: TObject; Contact: TContact; PossibleLinks: TPossibleLinks;
  1648.       var OtherContact: TContact);
  1649.   protected
  1650.     FScriptEventName: string;
  1651.     FScriptEventParams: array of Variant;
  1652.     procedure HandleRinging;
  1653.     procedure HandleMessage(var Msg: TFmaHandleMessage); message FMA_HANDLEMESSAGE;
  1654.     procedure WM_ENDSESSION(var Msg: TMessage); message WM_ENDSESSION;
  1655.     function IsT610Clone: boolean;
  1656.   public
  1657.     { Public declarations }
  1658. {$IFNDEF VER150}
  1659.     ThemeManager1: TThemeManager;
  1660. {$ENDIF}
  1661.     FStartupOptions: TStartupOptions;
  1662.     FProximityOptions: TProximityOptions;
  1663.     FTextMessageOptions: TTextMessageOptions;
  1664.     ActiveThread: TWaitThread;
  1665.     FBusy, FWaitingOK, FScriptRunning, FScriptInitialized, FScriptErrorOccur, FBatteryLow, FBatteryWarning: boolean;
  1666.     FFmaMutex,FWaitCompleteIsBusyEvent,FWaitCompleteEvent,FMSec,FInactivityTimeout: Cardinal;
  1667.     FDoCharConvertion,FObexConnecting,FAbort,FTimedout,FShowDiagram,FShowTodayCaption,FClearPhoneMessage: Boolean;
  1668.     FOutlookConfirmed: array[TContactAction] of TConfirmation;
  1669.     FAutolinkContacts: Boolean;
  1670.     FWaitStr,FLastCommand,FamCommand: String;
  1671.     FObex: TObex;
  1672.  
  1673.     // forms
  1674.     frmSIMEdit: TfrmSIMEdit;
  1675.     frmMsgView: TfrmMsgView;
  1676.     frmInfoView: TfrmInfoView;
  1677.     frmSyncPhonebook: TfrmSyncPhonebook;
  1678.     frmExplore: TfrmExplore;
  1679.     frmEditor: TfrmEditor;
  1680.  
  1681.     FNodeContactsME, FNodeContactsSM, FNodeProfiles, FNodeGroups, FNodeCalls, FNodeCallsIn, FNodeCallsOut, FNodeCallsMissed,
  1682.     FNodeObex, FNodeOrganizer, FNodeBookmarks, FNodeScripts: TtntTreeNode;
  1683.  
  1684.     FNodeMsgInbox, FNodeMsgSent, FNodeMsgOutbox, FNodeMsgDrafts, FNodeMsgArchive: TtntTreeNode;
  1685.  
  1686.     FSMSCounterReseted,FSMSDoWarning,FSMSDoReset: boolean;
  1687.     FSMSCounter, FSMSWarning, FSMSCounterResetDay: Integer;
  1688.     FSyncConflict,FClockSync: Integer;
  1689.     FBookmarkRootFolder: string;
  1690.     FOutlookSyncConflict: Integer;
  1691.     FOutlookConfirmAdding, FOutlookConfirmUpdating, FOutlookConfirmDeleting: Boolean;
  1692.     FOutlookCategories,FSelectedOutlookFolders: String;
  1693.     FOutlookNewAction: Integer;
  1694.     FOutlookNewContactsFolder: String;
  1695.     FLastMessageStore: String[2];
  1696.  
  1697.     FConnectionType,FExplorerStartupMode: Integer;
  1698.     FConnected,FConnectingComplete,FConnectingStarted: Boolean;
  1699.     FDontProgress,FProgressLongOnly,FProgressRestoredOnly: Boolean;
  1700.     FEmergencyMode,FUseCNMIMode3,FStatusReport,FUseUTF8,FUseObex,FAlreadyInUseObex,FUseEBCA,FUseScript: Boolean;
  1701.     skipDeleteWarn,FAbortDetected,FAutoConnectionError,FOnACPower,LoadingDBFiles: Boolean;
  1702.     FSelOperator,FSelPhone: String;
  1703.     FSupportedCS: String;
  1704.     FKeyActivity: String;
  1705.     FKeyInactivityTimeout: Integer;
  1706.     FRxBuffer,FFavoriteRecipients,FFavoriteCalls: TStringList;
  1707.  
  1708.     { Mixer vars }
  1709.     L,R,M,FLastVolume:Integer;
  1710.     VD,MD,MS,Stereo:Boolean;
  1711.  
  1712.     { Diagram }
  1713.     function IsEBCAEnabled: boolean;
  1714.     function CanUseEBCA(IgnoreConnectingState: boolean = False): boolean;
  1715.  
  1716.     { text messages }
  1717.     function IsMoveToArchiveEnabled: boolean;
  1718.     procedure DownloadMessages(Node: TtntTreeNode);
  1719.     procedure DownloadAllMessages;
  1720.  
  1721.     { phonebook }
  1722.     procedure DownloadPhonebook;
  1723.  
  1724.     { This allows calling object methods as well (m.func) }
  1725.     procedure CallScriptMethod(FunctionName: string; Params: array of Variant);
  1726.     procedure ApplyEditorChanges;
  1727.  
  1728.     procedure RenderContactList; overload;
  1729.     procedure RenderContactList(var rootNode: TtntTreeNode); overload;
  1730.  
  1731.     { Bookmarks}
  1732.     procedure RenderBookmarkList(var rootNode: TtntTreeNode); overload;
  1733.  
  1734.     { Phone Database }
  1735.     function GetPhoneIdentity: string;
  1736.     procedure SetPhoneIdentity(ID: string);
  1737.     function ExtractPhoneIdentity(var Model,Serial: string): string;
  1738.  
  1739.     function GetDatabasePath: string;
  1740.     function LoadPhoneDataFiles(ID: string = ''): boolean;
  1741.     procedure ClearExplorerViews;
  1742.     procedure SaveData;
  1743.  
  1744.     { Text Messages }
  1745.     function GetChatWindow(Contact: string; AllowCreateNew: boolean = False): TfrmCharMessage;
  1746.     procedure ChatNotifyDel(PDU: String);
  1747.  
  1748.     procedure UpdateNewMessagesCounter(rootNode: TtntTreeNode; ModifyPDU: string = ''; MarkAsRead: boolean = True);
  1749.     function GetNewMessagesCounter(rootNode: TtntTreeNode): integer;
  1750.  
  1751.     procedure SaveMsgToFolder(var rootNode: TtntTreeNode; PDU: String;
  1752.       OverwriteOld: boolean = false; AsNew: boolean = true);
  1753.     procedure SaveToArchive(PDU: String; OverwriteOld: boolean = false);
  1754.     function DelMsgFromFolder(var rootNode: TtntTreeNode; PDU: string): Boolean;
  1755.     function DeleteSMS(index: Integer; memType: String): Boolean;
  1756.  
  1757.     function GetNextLongSMSRefference: string;
  1758.     procedure SentMessage(UDHI: String; msg: WideString; destNo: WideString; reqReply: Boolean=False;
  1759.       Flash: Boolean=False; StatusReq:Boolean=False; dcs: Integer=-1; SaveDraft: boolean = False);
  1760.  
  1761.     procedure Debug(str: String; PrefixTimestamp: boolean = True);
  1762.     procedure SyncLog(str: String; PrefixTimestamp: boolean = True);
  1763.     procedure ActivityLog(str: String; PrefixTimestamp: boolean = True);
  1764.  
  1765.     procedure Status(str: String; UpdateDebugLog: boolean = True);
  1766.  
  1767.     procedure TxAndWait(Data: string; WaitStr: String = 'OK');
  1768.     procedure ScheduleTxAndWait(Data: string; WaitStr: String = 'OK');
  1769.  
  1770.     function LookupContact(Number: String; DefaultName: string = ''): String;
  1771.     function LookupNumber(Contact: String): String;
  1772.  
  1773.     procedure InitBookmarks;
  1774.     procedure InitProfile;
  1775.     procedure InitGroups;
  1776.     procedure InitCalls; overload;
  1777.     procedure InitCalls(Node: TtntTreeNode); overload;
  1778.     procedure InitObexFolders;
  1779.  
  1780.     function ExplorerFindExtImage(Ext: string): integer;
  1781.     procedure ExplorerAddToGroup(GroupIndex: integer; Contact: WideString);
  1782.  
  1783.     procedure ExtractName(var Name,numType: WideString);
  1784.     function ExtractNumber(ContactNumber: WideString): WideString;
  1785.     function ExtractContact(ContactNumber: WideString): WideString;
  1786.     function ContactNumberByTel(ContactNumber: string): string;
  1787.     function ContactNumberByName(ContactName: string): string;
  1788.  
  1789.     function IsContactNumberSelected: boolean;
  1790.     function LocateSelContactNumber: string;
  1791.     function GetPartialNumber(Number: string): string;
  1792.  
  1793.     function LocatePBName(Where: string; Index: integer): string; overload;
  1794.     function LocatePBName(Where: string; Index: integer; var Number: string): string; overload;
  1795.     function LocatePBIndex(Where: string; Person: WideString; Phone: string): integer;
  1796.  
  1797.     function WriteSMS(memLocation, PDU: String; Stat: Integer = -1): boolean;
  1798.  
  1799.     procedure RefreshPhoneBook;
  1800.     procedure UpdateMEPhonebook;
  1801.     procedure UpdateSMPhonebook;
  1802.  
  1803.     procedure EnableKeyMonitor(TxDelay: boolean = False);
  1804.     procedure DisableKeyMonitor(TxDelay: boolean = False);
  1805.  
  1806.     procedure MinimizeApp;
  1807.     procedure VoiceCall(number: String);
  1808.     procedure VoiceAnswer;
  1809.     procedure VoiceHangUp(SilentMode: boolean = False);
  1810.  
  1811.     procedure DoAbort;
  1812.     procedure DoConnect;
  1813.     procedure DoDisconnect;
  1814.     procedure DoDisconnectTemporary;
  1815.     procedure RequestConnection(DoNotRefreshView: boolean = True);
  1816.  
  1817.     procedure DoProximityNear;
  1818.     procedure DoProximityAway;
  1819.     procedure DoProximityTest;
  1820.  
  1821.     procedure DoProcessOutbox;
  1822.  
  1823.     function GetMute: Boolean;
  1824.     function GetVolume: Integer;
  1825.     procedure SetMute(Mute: Boolean);
  1826.     procedure SetVolume(Percentage: Integer);
  1827.  
  1828.     function IsAutoConnect: boolean;
  1829.     function IsScriptInitialized: boolean;
  1830.     function CanShowProgress: boolean;
  1831.  
  1832.     { Obex folder routines }
  1833.     function FindObexFolderNode(AType: byte): TTntTreeNode; // 0-pics,1-snds
  1834.     function FindObexFolderName(AType: byte): WideString; // 0-pics,1-snds
  1835.  
  1836.     procedure SetActionState(act: TAction; state: Boolean);
  1837.  
  1838.     { Obex routines within Connect/disconnect block }
  1839.     procedure ObexConnect(Target: widestring = '');
  1840.     procedure ObexDisconnect;
  1841.  
  1842.     function ObexGetObject(Path: Widestring; var Where: TStringList;
  1843.       progress: boolean = False; FriendlyName: string = ''): cardinal; overload;
  1844.     function ObexGetObject(Path: Widestring; var stream: TStream;
  1845.       progress: boolean = False): cardinal; overload;
  1846.     function ObexPutObject(Path: Widestring; Stream: TStream;
  1847.       progress: boolean = False): WideString;
  1848.  
  1849.     { Direct obex calls }
  1850.     procedure ObexPutFile(filename: WideString; Delete: boolean = False; Silent: boolean = False);
  1851.     procedure ObexGetFile(filename,objname: WideString; Silent: boolean = False);
  1852.  
  1853.     procedure StartupInitialize;
  1854.     procedure ScriptInitialize;
  1855.     procedure ViewInitialize;
  1856.  
  1857.     procedure FloatingRectangles(Minimizing, OverrideUserSettings: Boolean);
  1858.     procedure ShowBaloonInfo(Text: string; Timeout: TBalloonHintTimeOut = 10);
  1859.  
  1860.     { Explorer properties }
  1861.     function FindExplorerChildNode(Named: WideString): TTntTreeNode;
  1862.     procedure ShowExplorerProperties(Node: TTntTreeNode);
  1863.   published
  1864.     procedure ActionToolsEditProfileExecute(Sender: TObject);
  1865.     procedure Explore(Node: TTntTreeNode);
  1866.     //
  1867.     property PhoneIdentity: string read GetPhoneIdentity write SetPhoneIdentity;
  1868.     property ScriptFilename: string read FScriptFile;
  1869.   end;
  1870.  
  1871. var
  1872.   Form1: TForm1;
  1873.   ExePath: WideString;
  1874.  
  1875. { Wait seconds if < 100, else miliseconds, but one can force as miliseconds }
  1876. procedure WaitASec(Seconds: integer = 1; ForceMSecs: boolean = False);
  1877.  
  1878. function GetSyncLogWindow: TfrmSyncLog;
  1879. function GetActivityLogWindow: TfrmActivityLog;
  1880.  
  1881. function EvenQuotes(const Str: String): Boolean;
  1882.  
  1883. implementation
  1884.  
  1885. uses ShlObj, uCalling, uAbout, uOptions, uNewMessage, uMobileAgentUI,
  1886.   uPostNote, uGlobal, uEditProfile, uPostURL, uConnProgress, uComposeSMS,
  1887.   uVersion, uStatusDlg, TeEngine, uFolderProps, Types, uOfflineProfile,
  1888.   SynEdit, uFMASync, uOutlookSync, uPromptConflict, uChooseLink,
  1889.   uOrganizeFavs, uCallContact, uAddToPhonebook, uXML, StrUtils,
  1890.   janXMLParser2, uInputQuery;
  1891.  
  1892. {$R *.dfm}
  1893.  
  1894. { Globals }
  1895.  
  1896. function EvenQuotes(const Str: String): Boolean;
  1897. var
  1898.   P: Integer;
  1899.   S: String;
  1900. begin
  1901.   S := Str;
  1902.   Result := False;
  1903.   repeat
  1904.     { D7 code
  1905.     P := PosEx('"', S, P + 1); }
  1906.     { D6 code }
  1907.     P := Pos('"',S); Delete(S,1,P);
  1908.     {}
  1909.     Result := not Result;
  1910.   until P = 0;
  1911. end;
  1912.  
  1913. procedure WaitASec(Seconds: integer; ForceMSecs: boolean);
  1914. var
  1915.   time: cardinal;
  1916. begin
  1917.   if Seconds < 1 then Seconds := 1;
  1918.   if (Seconds < 100) and not ForceMSecs then
  1919.     time := GetTickCount + cardinal(1000*Seconds)
  1920.   else
  1921.     time := GetTickCount + cardinal(Seconds);
  1922.   while (GetTickCount < time) and not Application.Terminated {and not Form1.FAbortDetected} do begin
  1923.     Sleep(20);
  1924.     Application.ProcessMessages;
  1925.   end;
  1926. end;
  1927.  
  1928. function GetSyncLogWindow: TfrmSyncLog;
  1929. var
  1930.   i: integer;
  1931. begin
  1932.   Result := nil;
  1933.   for i := 0 to Screen.FormCount-1 do
  1934.     if Screen.Forms[i] is TfrmSyncLog then
  1935.       begin
  1936.         Result := TfrmSyncLog(Screen.Forms[i]);
  1937.         break;
  1938.       end;
  1939.   if Result = nil then begin
  1940.     Result := TfrmSyncLog.Create(nil);
  1941.   end;
  1942. end;
  1943.  
  1944. function GetActivityLogWindow: TfrmActivityLog;
  1945. var
  1946.   i: integer;
  1947. begin
  1948.   Result := nil;
  1949.   for i := 0 to Screen.FormCount-1 do
  1950.     if Screen.Forms[i] is TfrmActivityLog then
  1951.       begin
  1952.         Result := TfrmActivityLog(Screen.Forms[i]);
  1953.         break;
  1954.       end;
  1955.   if Result = nil then begin
  1956.     Result := TfrmActivityLog.Create(nil);
  1957.   end;
  1958. end;
  1959.  
  1960. { Form1 }
  1961.  
  1962. procedure TForm1.Button12Click(Sender: TObject);
  1963. begin
  1964.   TntEdit2.Text := HTMLEncode(TntEdit1.Text);
  1965. end;
  1966.  
  1967. procedure TForm1.Button4Click(Sender: TObject);
  1968. begin
  1969.   TntEdit2.Text := UTF8Encode(TntEdit1.Text);
  1970. end;
  1971.  
  1972. procedure TForm1.Button5Click(Sender: TObject);
  1973. begin
  1974.   TntEdit2.Text := UTF8Decode(TntEdit1.Text);
  1975. end;
  1976.  
  1977. procedure TForm1.Button6Click(Sender: TObject);
  1978. var
  1979.   i: integer;
  1980.   s: string;
  1981. begin
  1982.   s := '';
  1983.   for i := 1 to length(TntEdit1.Text) do
  1984.     s := s + IntToHex(ord(TntEdit1.Text[i]),2);
  1985.   TntEdit2.Text := s;
  1986. end;
  1987.  
  1988. procedure TForm1.Button7Click(Sender: TObject);
  1989. var
  1990.   i: integer;
  1991.   s: string;
  1992.   a: string[2];
  1993.   b: char;
  1994. begin
  1995.   s := '';
  1996.   TntEdit1.Text := LowerCase(TntEdit1.Text);
  1997.   for i := 1 to length(TntEdit1.Text) div 2 do begin
  1998.     FillChar(b,SizeOf(b),0);
  1999.     a := copy(TntEdit1.Text,i*2-1,2);
  2000.     HexToBin(@a[1],@b,1);
  2001.     s := s + b;
  2002.   end;  
  2003.   TntEdit2.Text := s;
  2004. end;
  2005.  
  2006. procedure TForm1.Button8Click(Sender: TObject);
  2007. begin
  2008.   TntEdit2.Text := Str2QP(TntEdit1.Text);
  2009. end;
  2010.  
  2011. procedure TForm1.Button9Click(Sender: TObject);
  2012. begin
  2013.   TntEdit2.Text := QP2Str(TntEdit1.Text);
  2014. end;
  2015.  
  2016. procedure TForm1.Button1Click(Sender: TObject);
  2017. var
  2018.   str: TMemoryStream;
  2019. begin
  2020.   if RadioButton2.Checked then
  2021.     ObexConnect(Edit2.Text)
  2022.   else
  2023.     ObexConnect(ObexFolderBrowserServiceID);
  2024.   str := TMemoryStream.Create;
  2025.   try
  2026.     FObex.GetObject(cbObex.Text,str);
  2027.     memo1.Lines.LoadFromStream(str);
  2028.   finally
  2029.     str.free;
  2030.     ObexDisconnect;
  2031.   end;
  2032. end;
  2033.  
  2034. procedure TForm1.Button2Click(Sender: TObject);
  2035. var
  2036.   vCard: TVCard;
  2037. begin
  2038.   vCard := TVCard.Create;
  2039.   try
  2040.     vcard.Raw := Memo1.Lines;
  2041.     memo2.Lines.Clear;
  2042.     memo2.Lines.Add('Type = ' + vcard.VType);
  2043.     memo2.Lines.Add('Version = ' + vcard.Version);
  2044.     memo2.Lines.Add('Name = ' + vcard.Name);
  2045.     memo2.Lines.Add('Surname = ' + vcard.Surname );
  2046.     memo2.Lines.Add('Home = ' + vcard.TelHome );
  2047.     memo2.Lines.Add('Work = ' + vcard.TelWork );
  2048.     memo2.Lines.Add('Fax = ' + vcard.TelFax  );
  2049.     memo2.Lines.Add('Other = ' + vcard.TelOther );
  2050.     memo2.Lines.Add('Title = ' + vcard.Title );
  2051.     memo2.Lines.Add('Org = ' + vcard.Org );
  2052.     memo2.Lines.Add('Email = ' + vcard.email  );
  2053.     memo2.Lines.Add('XLUID = ' + vcard.LUID );
  2054.     if vcard.Photo <> nil then begin
  2055.       Image.Picture.Graphic.Assign(vcard.Photo);
  2056.     end;
  2057.   finally
  2058.     vCard.free;
  2059.   end;
  2060. end;
  2061.  
  2062. procedure TForm1.Button10Click(Sender: TObject);
  2063. begin
  2064.   ObexConnect(ObexFolderBrowserServiceID);
  2065.   try
  2066.     memo1.Lines.Clear;
  2067.     FObex.ChangeDir(cbObex.Text);
  2068.     memo1.Lines.Add('OK')
  2069.   finally
  2070.     ObexDisconnect;
  2071.   end;
  2072. end;
  2073.  
  2074. procedure TForm1.Button11Click(Sender: TObject);
  2075. var
  2076.   sl: TStringStream;
  2077. begin
  2078.   ObexConnect(ObexFolderBrowserServiceID);
  2079.   sl := TStringStream.Create('');
  2080.   try
  2081.     FObex.ChangeDir('');
  2082.     FObex.ChangeDir(cbObex.Text);
  2083.     FObex.List(sl);
  2084.     memo1.Lines.LoadFromStream(sl);
  2085.   finally
  2086.     sl.free;
  2087.     ObexDisconnect;
  2088.   end;
  2089. end;
  2090.  
  2091. { Form1 }
  2092.  
  2093. procedure TForm1.ActionConnectionConnectExecute(Sender: TObject);
  2094. var
  2095.   frmConnect: TfrmConnect;
  2096.   so1,so2,so3,so4: boolean;
  2097. begin
  2098.   Timer1.Enabled := False;
  2099.   if not Visible and (FormStorage1.StoredValue['StartMinimized'] = False) then begin
  2100.     Show;
  2101.     Update;
  2102.   end;
  2103.   try
  2104.     { Clear flags }
  2105.     FTimedout := False;
  2106.     FAutoConnectionError := False;
  2107.     FConnectingStarted := True;
  2108.     FConnectingComplete := False;
  2109.     FConnectionError := False;
  2110.     FConnected := False;
  2111.     FAbort := False;
  2112.     FAbortDetected := False;
  2113.     FEmergencyMode := True;
  2114.     FamCommand := '';
  2115.     try
  2116.       { Do connect }
  2117.       DoConnect;
  2118.       while not (FConnected or FAbortDetected or FTimedout or
  2119.         FConnectionError or Application.Terminated) do
  2120.         Application.ProcessMessages;
  2121.       if Application.Terminated then Abort;
  2122.  
  2123.       { Check for error }
  2124.       if FConnectionError then begin
  2125.         if not FAutoConnectionError then
  2126.           if FAbortDetected then
  2127.             if FBatteryLow then
  2128.               raise Exception.Create('Connection aborted by user or phone battery is too low')
  2129.             else
  2130.               raise Exception.Create('Connection aborted by user')
  2131.           else
  2132.             raise Exception.Create('Connection failed')
  2133.         else
  2134.           exit;
  2135.       end;
  2136.  
  2137.       if FConnected then begin
  2138.         { Allow auto-connect feature (if checked) }
  2139.         ActionConnectionMonitor.Tag := 1;
  2140.  
  2141.         { Success !!! }
  2142.         FConnectingComplete := True;
  2143.       end
  2144.       else
  2145.         exit;  
  2146.     except
  2147.       On E:Exception do begin
  2148.         Status(E.Message);
  2149.         DoDisconnect;
  2150.         { if aborted raise here to show this to user, and to
  2151.           cancel next connect operations.
  2152.         if not IsAutoConnect or FAbortDetected then
  2153.           raise;
  2154.         }
  2155.         if FTimedout or FAbortDetected then Abort;
  2156.       end;
  2157.     end;
  2158.   finally
  2159.     Timer1.Enabled := True;
  2160.     FConnectingStarted := False;
  2161.   end;
  2162.   { Connection is completed successfuly!
  2163.     Perform any startup operations... }
  2164.   if FDoSyncClock then SyncPhoneClock1.Click;
  2165.   frmConnect := GetProgressDialog;
  2166.   try
  2167.     so1 := FormStorage1.StoredValue['AutoInbox'];
  2168.     so2 := FormStorage1.StoredValue['AutoSync'];
  2169.     so3 := FormStorage1.StoredValue['AutoSyncOutlook'];
  2170.     so4 := FormStorage1.StoredValue['AutoBookmarks'];
  2171.     if (so1 or so2 or so3) and CanShowProgress then
  2172.       frmConnect.ShowProgress(FProgressLongOnly);
  2173.  
  2174.     if so1 then DownloadAllMessages;
  2175.     if so2 then ActionSyncPhonebook.Execute;
  2176.     if so3 then begin
  2177.       ActionSyncWithOutlook.Execute;
  2178.       { Also aaply changes to the phone }
  2179.       if so2 then ActionSyncPhonebook.Execute;
  2180.     end;
  2181.     { TODO: add sync bookmarks call }
  2182.     if so4 then ;
  2183.   finally
  2184.     FreeProgressDialog;
  2185.     { }
  2186.     EBCAState(True);
  2187.     EBCAState(frmInfoView.Visible,FormStorage1.StoredValue['StartMinimized'] = False);
  2188.     { Show SIM info }
  2189.     if FEmergencyMode then
  2190.       Status('SIM card not found or not a SIM card, emergency mode activated')
  2191.     else
  2192.       Status('SIM card found and ready with operator '+FSelOperator);
  2193.   end;
  2194. end;
  2195.  
  2196. procedure TForm1.ComPortAfterOpen(Sender: TObject);
  2197. var
  2198.   frmConnect: TfrmConnect;
  2199.   s,CurrentIdentity,model,serial,device: string;
  2200.   PhoneChanged: boolean;
  2201.   SockName: TSockAddr;
  2202.   i: integer;
  2203.   SelNode: TTntTreeNode;
  2204.   procedure DoReady;
  2205.   begin
  2206.     FAutoConnectionError := False;
  2207.     PhoneIdentity := CurrentIdentity;
  2208.     SetPanelText(0,'Connected');
  2209.     PlaySound(pChar('FMA_MEConnected'), 0, SND_ASYNC or SND_APPLICATION or SND_NODEFAULT);
  2210.     ShowBaloonInfo('Connected successfully to '+model+' phone.');
  2211.     ScriptEvent('OnConnected', []);
  2212.     { Update explorer view, if needed }
  2213.     if not FDoNotRefreshViewOnConnect then begin
  2214.       Explorer.Selected := SelNode;
  2215.       ExplorerChange(nil, Explorer.Selected);
  2216.     end;
  2217.     FDoNotRefreshViewOnConnect := False;
  2218.     if FTemporaryOffline then begin
  2219.       FTemporaryOffline := False;
  2220.       { Restore re-connect settings before last disconnect }
  2221.       ActionConnectionMonitor.Checked := FLastReconnect;
  2222.       ActionConnectionMonitor.Tag := byte(FLastReconnect);
  2223.     end;
  2224.   end;
  2225. begin
  2226.   SelNode := Explorer.Selected;
  2227.   FAlreadyInUseObex := False;
  2228.   FAutoConnectionError := IsAutoConnect;
  2229.   try
  2230.     ClearBuffer;
  2231.     { Go back to chart start point }
  2232.     if ChartShiftCnt <> 0 then begin
  2233.       with frmInfoView.Chart1.BottomAxis do Scroll(-ChartShiftCnt,False);
  2234.       ChartShiftCnt := 0;
  2235.     end;  
  2236.     frmInfoView.Chart1.Page := 1;
  2237.     frmInfoView.Chart1.Series[0].Clear;
  2238.     frmInfoView.Chart1.Series[1].Clear;
  2239.     frmInfoView.Chart1.Series[2].Clear;
  2240.  
  2241.     if not IsAutoConnect then Status('Connecting...');
  2242.     CoolTrayIcon1.Hint := 'Fma - Connecting...';
  2243.     CoolTrayIcon1.CycleIcons := True;
  2244.     try
  2245.       frmConnect := GetProgressDialog;
  2246.       try
  2247.         { Show progress if not auto-connecting and if enabled in options }
  2248.         if not IsAutoConnect and CanShowProgress then begin
  2249.           { If so, always do it, ignore delay option, since we have to see all connect steps }
  2250.           frmConnect.Initialize(26,'Searching Device...'); // for total, count IncProgress calls below - 1!
  2251.           frmConnect.ShowProgress(False);
  2252.         end;
  2253.  
  2254.         //if not IsAutoConnect then Debug('Initializing phone...');
  2255.         try TxAndWait('ATE0'); except; end;
  2256.         if FAbortDetected or FTimedout then Abort;
  2257.         frmConnect.IncProgress(1);
  2258.  
  2259.         FConnected := True;
  2260.         SetPanelText(0,'Negotiate');
  2261.         ActionConnectionToggle.Update;
  2262.  
  2263.         //if not IsAutoConnect then Debug('Check for Battery and Charging support');
  2264.         try
  2265.           TxAndWait('AT*EBCA=?');
  2266.           TxAndWait('AT*EBCA=0');
  2267.           FUseEBCA := True;
  2268.         except
  2269.           FUseEBCA := False;
  2270.           Debug('Battery and Charging Algorithm not supported!');
  2271.         end;
  2272.         if FAbortDetected or FTimedout then Abort;
  2273.         frmConnect.IncProgress(1);
  2274.  
  2275.         { Retrieve phone model, device name and serial number }
  2276.         frmConnect.SetDescr('Identifying phone');
  2277.         if IsAutoConnect then Debug('Auto-connect: Identify phone model')
  2278.           else Debug('Identify phone model');
  2279.         try
  2280.           TxAndWait('ATI');
  2281.           model := FRxBuffer[0];
  2282.           if Trim(model) = '' then model := 'Unknown';
  2283.         except
  2284.           Debug('Error: Could not identify phone model!');
  2285.           Abort;
  2286.         end;
  2287.         if FAbortDetected or FTimedout then Abort;
  2288.         frmConnect.IncProgress(1);
  2289.  
  2290.         try
  2291.           if FConnectionType = 0 then begin
  2292.             i := WBtSocket.GetPeerName(SockName,Sizeof(SockName));
  2293.             if i <> SOCKET_ERROR then device := StrPas(@SockName.sa_data[0])
  2294.             else device := '';
  2295.           end else
  2296.           if FConnectionType = 1 then
  2297.             device := WIrSocket.GetConnectedDevices.Items[0].irdaDeviceName
  2298.           else begin
  2299.             TxAndWait('AT+CGMM');
  2300.             device := Form1.FRxBuffer[0];
  2301.           end
  2302.         except
  2303.           device := '';
  2304.         end;
  2305.         if FAbortDetected or FTimedout then Abort;
  2306.         frmConnect.IncProgress(1);
  2307.  
  2308.         try
  2309.           TxAndWait('AT+CGSN');
  2310.           serial := Form1.FRxBuffer[0];
  2311.         except
  2312.           serial := 'Unknown';
  2313.         end;
  2314.         if FAbortDetected or FTimedout then Abort;
  2315.         frmConnect.IncProgress(1);
  2316.  
  2317.         { Detect phone database state }
  2318.         frmConnect.SetDescr('Opening phone database');
  2319.         CurrentIdentity := ExtractPhoneIdentity(model,serial);
  2320.         PhoneChanged := AnsiCompareText(PhoneIdentity,CurrentIdentity) <> 0;
  2321.         Debug('Auto-connect: Prev phone ID: '+PhoneIdentity);
  2322.         Debug('Auto-connect: Curr phone ID: '+CurrentIdentity);
  2323.         if IsAutoConnect then begin
  2324.           if PhoneChanged then begin
  2325.             Debug('Auto-connect: NEW phone found!');
  2326.             Debug('Doing normal connect...');
  2327.           end
  2328.           else begin
  2329.             Debug('Auto-connect: Previous phone found!');
  2330.             Debug('Doing fast re-connect...');
  2331.           end;
  2332.         end;
  2333.         { Load phone database settings and show as connected }
  2334.         Debug('Opening phone database');
  2335.         try
  2336.           LoadPhoneDataFiles(CurrentIdentity);
  2337.         except
  2338.         end;
  2339.         if FSelPhone = '' then begin
  2340.           CoolTrayIcon1.Hint := 'Fma - Connected to '+model+' phone';
  2341.           if device = '' then
  2342.             Explorer.Items.GetFirstNode.Text := 'My '+model+' Phone'
  2343.           else
  2344.             Explorer.Items.GetFirstNode.Text := 'My '+model+' Phone ('+device+')';
  2345.         end
  2346.         else begin
  2347.           CoolTrayIcon1.Hint := 'Fma - Connected to '+FSelPhone;
  2348.           Explorer.Items.GetFirstNode.Text := FSelPhone;
  2349.         end;
  2350.         SetPanelText(1,model);
  2351.         //if IsT610Clone then Explorer.GetFirstNode.ImageIndex := 45 else
  2352.         Explorer.Items.GetFirstNode.ImageIndex := 52;
  2353.         CoolTrayIcon1.HideBalloonHint; // if previous 'failed' is shown, hide it
  2354.         frmConnect.IncProgress(1);
  2355.  
  2356.         if IsAutoConnect then begin
  2357.           if not PhoneChanged then begin
  2358.             { Cancel auto-connect }
  2359.             ActionConnectionMonitor.Tag := 0;
  2360.             FAutoConnectionError := False;
  2361.             if CanShowProgress then
  2362.               frmConnect.ShowProgress(False);
  2363.           end;
  2364.           DoProximityNear;
  2365.         end;
  2366.  
  2367.         frmConnect.SetDescr('Switching character set');
  2368.         Debug('Try switching character set to UTF-8 or Latin-1');
  2369.         try
  2370.           FUseUTF8 := False;
  2371.           TxAndWait('AT+CSCS=?');
  2372.           { UTF-8 has priority than Laton-1 - UTF gives us cyrillic support }
  2373.           if Pos('UTF-8',FSupportedCS) <> 0 then
  2374.             begin
  2375.               TxAndWait('AT+CSCS="UTF-8"');
  2376.               FUseUTF8 := True;
  2377.             end
  2378.           else
  2379.             if Pos('8859-1',FSupportedCS) <> 0 then
  2380.               TxAndWait('AT+CSCS="8859-1"')
  2381.             else
  2382.               Debug('TODO: Add UCS-2 support!');
  2383.           FDoCharConvertion := False;
  2384.         except;
  2385.           Debug('Will convert characters manually');
  2386.           FDoCharConvertion := True;
  2387.         end;
  2388.         if FAbortDetected or FTimedout then Abort;
  2389.         frmConnect.IncProgress(1);
  2390.  
  2391.         frmConnect.SetDescr('Checking voice support');
  2392.  
  2393.         Debug('Check for special voice dialing commands (dial) (T68, T610)');
  2394.         try
  2395.           TxAndWait('AT*EVD=?');
  2396.           FHaveVoiceDialCommand_Dial := True;
  2397.         except;
  2398.           Debug('Voice dialing dial command not supported! Will use old style dialing commands');
  2399.           FHaveVoiceDialCommand_Dial := False;
  2400.         end;
  2401.  
  2402.         Debug('Check for special voice dialing commands (answer) (T68, T610)');
  2403.         try
  2404.           TxAndWait('AT*EVA=?');
  2405.           FHaveVoiceDialCommand_Answer := True;
  2406.         except;
  2407.           Debug('Voice dialing answer command not supported! Will use old style dialing commands');
  2408.           FHaveVoiceDialCommand_Answer := False;
  2409.         end;
  2410.  
  2411.         Debug('Check for special voice dialing commands (hangup) (T68, T610)');
  2412.         try
  2413.           TxAndWait('AT*EVH=?');
  2414.           FHaveVoiceDialCommand_Hangup := True;
  2415.         except;
  2416.           Debug('Voice dialing hangup command not supported! Will use old style dialing commands');
  2417.           FHaveVoiceDialCommand_Hangup := False;
  2418.         end;
  2419.  
  2420.         if FAbortDetected or FTimedout then Abort;
  2421.         frmConnect.IncProgress(1);
  2422.  
  2423.         frmConnect.SetDescr('Checking SIM status');
  2424.         Debug('Check SIM status');
  2425.         try TxAndWait('AT+CPIN?'); except; end;
  2426.         try
  2427.           TxAndWait('AT+COPS=3,0');
  2428.           TxAndWait('AT+COPS?');
  2429.         except; end;
  2430.         if FAbortDetected or FTimedout then Abort;
  2431.         frmConnect.IncProgress(1);
  2432.  
  2433.         frmConnect.SetDescr('Setting caller ID');
  2434.         Debug('Request calling line ident');
  2435.         try TxAndWait('AT+CLIP=1'); except; end;
  2436.         if FAbortDetected or FTimedout then Abort;
  2437.         frmConnect.IncProgress(1);
  2438.  
  2439.         frmConnect.SetDescr('Setting presentation ID');
  2440.         Debug('Request Alpha Tags');
  2441.         try TxAndWait('AT*EIPS=1,1'); except; end;
  2442.         try TxAndWait('AT*EIPS=2,1'); except; end;
  2443.         if FAbortDetected or FTimedout then Abort;
  2444.         frmConnect.IncProgress(1);
  2445.  
  2446.         frmConnect.SetDescr('Setting call monitoring');
  2447.         Debug('Enable Call Monitoring');
  2448.         try TxAndWait('AT*ECAM=1'); except; end;
  2449.         if FAbortDetected or FTimedout then Abort;
  2450.         frmConnect.IncProgress(1);
  2451.  
  2452.         // new msg indication
  2453.         frmConnect.SetDescr('Setting sms notification');
  2454.         Debug('Enable New Msg Notification');
  2455.         try
  2456.           TxAndWait('AT+CNMI=?');
  2457.           if FStatusReport then
  2458.             s := ',0,1'
  2459.           else begin
  2460.             s := '';
  2461.             Debug('New Messages: Status Report to Terminal not supported!');
  2462.           end;
  2463.           if FUseCNMIMode3 then
  2464.             TxAndWait('AT+CNMI=3,1'+s)
  2465.           else begin
  2466.             Debug('New Messages: Class 3 Delivery not supported!');
  2467.             try
  2468.               TxAndWait('AT+CNMI=2,1'+s);
  2469.             except
  2470.               Debug('New Messages: Class 2 Delivery not supported!');
  2471.               //TxAndWait('AT+CNMI=1,1'+s); // trying to guess (1)
  2472.             end;
  2473.           end;
  2474.         except; end;
  2475.         if FAbortDetected or FTimedout then Abort;
  2476.         frmConnect.IncProgress(1);
  2477.  
  2478.         frmConnect.SetDescr('Setting mute notification');
  2479.         Debug('Enable Music Mute Notification');
  2480.         try TxAndWait('AT*EMIR=1'); except; end;
  2481.         if FAbortDetected or FTimedout then Abort;
  2482.         frmConnect.IncProgress(1); // total 14
  2483.  
  2484.         if not IsAutoConnect then begin
  2485.           FUseObex := False;
  2486.           if not FStartupOptions.NoObex then begin
  2487.             frmConnect.SetDescr('Checking Obex support');
  2488.             Debug('Checking EOBEX Capability');
  2489.             try
  2490.               TxAndWait('AT*EOBEX=?');
  2491.               FUseObex := True;
  2492.               LMDFMDrop.Enabled := True;
  2493.               Debug('Obex is OK');
  2494.             except
  2495.               Debug('E0BEX not supported');
  2496.             end;
  2497.             if FAbortDetected or FTimedout then Abort;
  2498.           end;
  2499.           frmConnect.IncProgress(1);
  2500.  
  2501.           if FUseObex then begin
  2502.             frmConnect.SetDescr('Build contact structure');
  2503.             Debug('Obex Build contact structure');
  2504.             if not FStartupOptions.NoIRMC then
  2505.               try
  2506.                 GetContactRestrict;
  2507.               except
  2508.                 Debug('Obex Build contact by defaults');
  2509.               end
  2510.             else
  2511.               try frmSyncPhonebook.OnConnected; except end;
  2512.             Status('Connecting...'); // restore status
  2513.             if FAbortDetected or FTimedout then Abort;
  2514.             frmConnect.IncProgress(1);
  2515.  
  2516.             if not FStartupOptions.NoFolders then begin
  2517.               frmConnect.SetDescr('Build phone folders');
  2518.               Debug('Obex Build phone folders');
  2519.               try InitObexFolders; except; end;
  2520.               if FAbortDetected or FTimedout then Abort;
  2521.             end
  2522.             else
  2523.               Debug('Startup: Skipping folders loading');
  2524.             frmConnect.IncProgress(1);
  2525.           end
  2526.           else begin
  2527.             frmConnect.SetDescr('Retrieving Phone info');
  2528.             Debug('Retrieving Phone info');
  2529.             try frmSyncPhonebook.OnConnected; except end;
  2530.             if FAbortDetected or FTimedout then Abort;
  2531.             frmConnect.IncProgress(2);
  2532.           end;
  2533.         end
  2534.         else
  2535.           frmConnect.IncProgress(3);
  2536.  
  2537.         frmConnect.SetDescr('Checking keypad support');
  2538.         Debug('Checking keypad support');
  2539.         try
  2540.           TxAndWait('AT+CKPD=?');
  2541.           ActionKeyPad.Visible := True;
  2542.           frmKeyPad.SetKeysMode(IsT610Clone);
  2543.         except
  2544.           Debug('Send key (keypad) not supported');
  2545.         end;
  2546.         if FAbortDetected or FTimedout then Abort;
  2547.         frmConnect.IncProgress(1); // total 18
  2548.  
  2549.         if not IsAutoConnect then begin
  2550.           if not FStartupOptions.NoProfiles then begin
  2551.             frmConnect.SetDescr('Retrieving profiles');
  2552.             Debug('Retrieving profiles');
  2553.             try InitProfile; except; end;
  2554.             if FAbortDetected or FTimedout then Abort;
  2555.           end;
  2556.           frmConnect.IncProgress(1);
  2557.  
  2558.           if not FStartupOptions.NoGroups then begin
  2559.             frmConnect.SetDescr('Retrieving groups');
  2560.             Debug('Retrieving groups');
  2561.             try InitGroups; except; end;
  2562.             if FAbortDetected or FTimedout then Abort;
  2563.           end
  2564.           else
  2565.             Debug('Startup: Skipping groups loading');
  2566.           frmConnect.IncProgress(1);
  2567.  
  2568.           if not FStartupOptions.NoCalls then begin
  2569.             frmConnect.SetDescr('Retrieving calls');
  2570.             Debug('Retrieving calls');
  2571.             try InitCalls; except; end;
  2572.             if FAbortDetected or FTimedout then Abort;
  2573.           end;
  2574.           frmConnect.IncProgress(1);
  2575.  
  2576.           if not FStartupOptions.NoBookmarks then begin
  2577.             frmConnect.SetDescr('Retrieving bookmarks');
  2578.             Debug('Retrieving bookmarks');
  2579.             try InitBookmarks; except; end;
  2580.             if FAbortDetected or FTimedout then Abort;
  2581.           end;
  2582.           frmConnect.IncProgress(1);
  2583.  
  2584.           frmConnect.SetDescr('Retrieving SIM info');
  2585.           Debug('Retrieving SIM info');
  2586.           try frmSIMEdit.OnConnected; except; end;
  2587.           if FAbortDetected or FTimedout then Abort;
  2588.           frmConnect.IncProgress(1);
  2589.         end
  2590.         else
  2591.           frmConnect.IncProgress(5);
  2592.  
  2593.         frmConnect.SetDescr('Retrieving phone info');
  2594.         Debug('Retrieve Identification Information');
  2595.         try frmInfoView.GetIdent; except; end;
  2596.         if FAbortDetected or FTimedout then Abort;
  2597.         frmConnect.IncProgress(1); // total 24
  2598.  
  2599.         frmConnect.SetDescr('Retrieving phone status');
  2600.         Debug('Retrieve Signal and Battery Status');
  2601.         try
  2602.           TxAndWait('AT+CBC');
  2603.         except;
  2604.         end;
  2605.         if FAbortDetected or FTimedout then Abort;
  2606.         frmConnect.IncProgress(1);
  2607.  
  2608.         try
  2609.           TxAndWait('AT+CSQ');
  2610.         except;
  2611.         end;
  2612.         if FAbortDetected or FTimedout then Abort;
  2613.         frmConnect.IncProgress(1);
  2614.  
  2615.         if not IsAutoConnect then begin
  2616.           if FClockSync <> 2 then begin // is it enabled?
  2617.             frmConnect.SetDescr('Checking phone clock');
  2618.             Debug('Synchronizing Phone Clock with PC Clock');
  2619.             try TxAndWait('AT+CCLK?'); except; end;
  2620.           end;
  2621.           if FAbortDetected or FTimedout then Abort;
  2622.         end;
  2623.         frmConnect.IncProgress(1); // total 27
  2624.  
  2625.         if FAutoProfile then begin
  2626.           cbProfile.ItemIndex := cbProfile.Items.IndexOf(FormStorage1.StoredValue['AutoProfile']);
  2627.           if cbProfile.ItemIndex <> -1 then cbProfileChange(cbProfile);
  2628.         end;
  2629.       finally
  2630.         FreeProgressDialog;
  2631.         if Explorer.Selected <> nil then
  2632.           Explorer.Selected.MakeVisible;
  2633.       end;
  2634.       DoReady;
  2635.     finally
  2636.       CoolTrayIcon1.CycleIcons := False;
  2637.       CoolTrayIcon1.IconIndex := 0;
  2638.     end;
  2639.     CoolTrayIcon1.IconIndex := 5; // show as connected
  2640.     frmInfoView.UpdateWelcomePage(True);
  2641.   except
  2642.     on e: Exception do begin
  2643.       FConnectionError := True;
  2644.       if IsAutoConnect then begin
  2645.         if FAbortDetected then
  2646.           ActionConnectionMonitor.Tag := 0; // cancel auto-connect too
  2647.         DoDisconnect;
  2648.       end
  2649.       else begin
  2650.         FAutoConnectionError := False;
  2651.         DoDisconnect;
  2652.         if not Application.Terminated then
  2653.           if FAbortDetected then
  2654.             CoolTrayIcon1.ShowBalloonHint(Application.Title,'Connection aborted!',bitError,10)
  2655.           else
  2656.             CoolTrayIcon1.ShowBalloonHint(Application.Title,'Connection failed!',bitError,10);
  2657.       end;
  2658.     end;  
  2659.   end;
  2660. end;
  2661.  
  2662. procedure TForm1.ActionConnectionDisconnectExecute(Sender: TObject);
  2663. begin
  2664.   if Sender <> nil then
  2665.     ActionConnectionMonitor.Tag := 0;
  2666.   try
  2667.     if not IsAutoConnect then Status('Disconnecting...');
  2668.     if FObex.Connected then FObex.ForceAbort;
  2669.     DoDisconnect;
  2670.     Status('');
  2671.   except
  2672.     Status('Disconnection Error');
  2673.   end;
  2674. end;
  2675.  
  2676. procedure TForm1.ComPortAfterClose(Sender: TObject);
  2677. begin
  2678.   FWaitStr := 'ERROR';
  2679.   SetEvent(FWaitCompleteEvent);
  2680.   FMessage := '';
  2681.   FLastBaloonMessagePDU := '';
  2682.  
  2683.   if (Sender <> nil) and not FExiting and FConnected and FConnectingComplete and not Application.Terminated then begin
  2684.     PlaySound(pChar('FMA_MEDisconnected'), 0, SND_ASYNC or SND_APPLICATION or SND_NODEFAULT);
  2685.     ScriptEvent('OnDisconnected', []);
  2686.   end;
  2687.  
  2688.   FBatteryWarning := False;
  2689.   FConnectingStarted := False;
  2690.   FConnectingComplete := False;
  2691.   FConnected := False;
  2692.   FObexConnecting := False;
  2693.  
  2694.   SetPanelText(0, 'Disconnected');
  2695.   SetPanelText(1);
  2696.   SetPanelText(2);
  2697.   SetPanelText(3);
  2698.  
  2699.   if (frmCalling <> nil) and frmCalling.Visible then
  2700.     frmCalling.Close;
  2701.  
  2702.   CoolTrayIcon1.CycleIcons := False;
  2703.   CoolTrayIcon1.IconIndex := 0;
  2704.   CoolTrayIcon1.Hint := 'Fma - Not Connected';
  2705.   if (Sender <> nil) and not FExiting and not FAutoConnectionError and not Application.Terminated then
  2706.     if FTemporaryOffline then
  2707.       ShowBaloonInfo('Phone is temporary disconnected...')
  2708.     else
  2709.       ShowBaloonInfo('Phone disconnected or out of range.');
  2710.  
  2711.   ActionKeyPad.Visible := False;
  2712.   LMDFMDrop.Enabled := False;
  2713.  
  2714.   if FSelPhone <> '' then
  2715.     Explorer.Items.GetFirstNode.Text := FSelPhone
  2716.   else
  2717.     Explorer.Items.GetFirstNode.Text := 'My Phone';
  2718.   if Explorer.Items.GetFirstNode.ImageIndex = 45 then
  2719.     Explorer.Items.GetFirstNode.ImageIndex := 44
  2720.   else
  2721.     Explorer.Items.GetFirstNode.ImageIndex := 51;
  2722. end;
  2723.  
  2724. procedure TForm1.HandleMessage(var Msg: TFmaHandleMessage);
  2725.   var
  2726.     AMsg: String;
  2727. begin
  2728.   AMsg := Msg.Message;
  2729.   StrDispose(Msg.Message);
  2730.  
  2731.   AMsg := trim(AMsg);
  2732.   Debug('[RX] ' + AMsg);
  2733.   // Reset inactivity timeout
  2734.   if pos('*EBCA', AMsg) <> 1 then
  2735.     FMSec := GetTickCount + FInactivityTimeout;
  2736.   try
  2737.     try
  2738.       if pos('RING', AMsg) = 1 then begin
  2739.         HandleRinging;
  2740.       end
  2741.       else if pos('*ECAV', AMsg) = 1 then begin
  2742.         HandleECAV(AMsg);
  2743.       end
  2744.       else if pos('*EOLP', AMsg) = 1 then begin
  2745.         HandleECAV(AMsg);
  2746.       end
  2747.       else if pos('*ELIP', AMsg) = 1 then begin
  2748.         HandleECAV(AMsg);
  2749.       end
  2750.       else if pos('+CSQ', AMsg) = 1 then begin
  2751.         HandleStatus(AMsg);
  2752.       end
  2753.       else if pos('+CBC', AMsg) = 1 then begin
  2754.         HandleStatus(AMsg);
  2755.       end
  2756.       else if pos('+CMTI', AMsg) = 1 then begin
  2757.         PlaySound(pChar('FMA_SMSReceived'), 0, SND_ASYNC or SND_APPLICATION or SND_NODEFAULT);
  2758.         { Show baloon on first message only }
  2759.         if FMsgM and not FTextMessageOptions.NoBaloon then begin
  2760.           if FNewMessageList.Count = 0 then
  2761.             ShowBaloonInfo('New message received.',60);
  2762.         end
  2763.         else
  2764.           Status('New message received');
  2765.         { Add msg to queue, will download later (see timer2) }
  2766.         FNewMessageList.Add(AMsg);
  2767.       end
  2768.       else if pos('+CKEV', AMsg) = 1 then begin
  2769.         HandleCKEV(AMsg);
  2770.       end
  2771.       else if pos('+CPMS', AMsg) = 1 then begin
  2772.         HandleCPMS(AMsg);
  2773.       end
  2774.       else if pos('+CIEV', AMsg) = 1 then begin
  2775.         HandleCIEV(AMsg);
  2776.       end
  2777.       else if pos('+COPS', AMsg) = 1 then begin
  2778.         HandleCOPS(AMsg);
  2779.       end
  2780.       else if pos('+CSCS', AMsg) = 1 then begin
  2781.         HandleCSCS(AMsg);
  2782.       end
  2783.       else if pos('+CPIN', AMsg) = 1 then begin
  2784.         HandleCPIN(AMsg);
  2785.       end
  2786.       else if pos('+CCLK', AMsg) = 1 then begin
  2787.         HandleCCLK(AMsg);
  2788.       end
  2789.       else if pos('+CNMI', AMsg) = 1 then begin
  2790.         HandleCNMI(AMsg);
  2791.       end
  2792.       else if pos('+CLCK', AMsg) = 1 then begin
  2793.         HandleCLCK(AMsg);
  2794.       end
  2795.       else if pos('*EMIV', AMsg) = 1 then begin
  2796.         HandleEMIV(AMsg);
  2797.       end
  2798.       else if pos('*EAAI', AMsg) = 1 then begin
  2799.         ScriptEvent('OnAMRoot', []);
  2800.       end
  2801.       else if (pos('*EAMI', AMsg) = 1) or (pos('*EAII', AMsg) = 1) then begin
  2802.         HandleEAMI(AMsg);
  2803.       end
  2804.       else if (pos('*EBCA', AMsg) = 1) then begin
  2805.         HandleEBCA(AMsg);
  2806.       end
  2807.       else begin
  2808.         if FRxBuffer <> nil then
  2809.           FRxBuffer.Add(AMsg);
  2810.   
  2811.         if FWaitStr <> '' then begin
  2812.           if FWaitStr = AMsg then begin
  2813.             FWaitStr := ''; // This is a signal to the thread the correct result is found
  2814.             SetEvent(FWaitCompleteEvent);
  2815.           end;
  2816.  
  2817.           if pos('ERROR: 515', AMsg) > 0  then begin
  2818.             Debug('Please wait, init in progress...');
  2819.             // 515 means "please wait, init in progress"
  2820.             // so skip it.
  2821.           end
  2822.           else if (pos('NO CARRIER', AMsg) > 0) and (FLastCommand = 'AT*EOBEX') then begin
  2823.             Debug('Obex already in use or connect failed');
  2824.             FAlreadyInUseObex := True;
  2825.             FObexConnecting := False;
  2826.             FWaitStr := '';
  2827.             SetEvent(FWaitCompleteEvent);
  2828.           end
  2829.           else if pos('ERROR', AMsg) > 0  then begin
  2830.             FWaitStr := 'ERROR';
  2831.             SetEvent(FWaitCompleteEvent);
  2832.           end;
  2833.         end;
  2834.       end;
  2835.     finally
  2836.       if AMsg = 'OK' then begin
  2837.         FWaitingOK := False;
  2838.         FScriptRunning := False;
  2839.       end;
  2840.     end;
  2841.   except
  2842.     { silent errors }
  2843.   end;
  2844.   inherited;
  2845. end;
  2846.  
  2847. // --------------------------------------------------------------------------------------
  2848.  
  2849. procedure TForm1.TxAndWait(Data, WaitStr: String);
  2850. var
  2851.   i: Integer;
  2852. //  msg: TMsg;
  2853. //  Hndl: THandle;
  2854. begin
  2855.   if FRxBuffer <> nil then
  2856.     {
  2857.     if not FObex.Connected and (Length(Data) > 250) then begin
  2858.       Debug('[TX] ERROR: Data length > 250 Chars, dropped!');
  2859.       Abort;
  2860.     end;
  2861.     }
  2862.     if WaitStr = '' then begin
  2863.       { Transmit data immediately and don't wait for a response }
  2864.       Debug('[TX] ' + Data);
  2865.       if FConnectionType = 0 then WBtSocket.SendStr(Data + #13)
  2866.       else if FConnectionType = 1 then WIrSocket.SendStr(Data + #13)
  2867.       else ComPort.WriteStr(Data + #13); // Serial
  2868.     end
  2869.     else try
  2870.       { If Data is '' then just check for stray WaitStr response.
  2871.         Create new thread for sending data, it will update FMSec as well }
  2872.       with TWaitThread.Create(Data,WaitStr) do
  2873.       try
  2874.         { This is the most stable version, so I shall keep it }
  2875.         while not Finished do begin
  2876.           Sleep(25); // give some CPU time to other threads, should b tested with Automation objects's calls!!
  2877.           Application.ProcessMessages;
  2878.           if FAbort or Application.Terminated then Abort;
  2879.         end;
  2880.         {}
  2881.  
  2882.         { TESTNG...
  2883.         repeat
  2884.           if (WaitForSingleObject(FWaitCompleteIsBusyEvent,50) = WAIT_OBJECT_0) and Finished then break;
  2885.           Application.ProcessMessages;
  2886.           if FAbort or Application.Terminated then Abort;
  2887.         until False;
  2888.         {}
  2889.         {
  2890.         while not Finished and (WaitForSingleObject(Handle, 50) = WAIT_TIMEOUT) do begin
  2891.           if FAbort or Application.Terminated then Abort;
  2892.           Application.ProcessMessages;
  2893.         end;
  2894.         {}
  2895.         {
  2896.         Hndl := Handle; // Could we use FWaitCompleteIsBusyEvent instead?
  2897.         while not Finished and // we sould have timeout here to allow Tx/Rc flow without delays 
  2898.           (MsgWaitForMultipleObjects(1, Hndl, False, 50, QS_ALLEVENTS) = (WAIT_OBJECT_0 + 1)) do begin
  2899.           Application.ProcessMessages;
  2900.           if FAbort or Application.Terminated then Abort;
  2901.         end;
  2902.         {
  2903.         // 1. wait until thread starts transmitting data
  2904.         while not Started do begin
  2905.           Application.ProcessMessages;
  2906.           if FAbort or Application.Terminated then Abort;
  2907.         end;
  2908.         // 2. wait until thread ends transmitting data
  2909.         while not Finished do begin
  2910.           // wait for any input or an signaled object
  2911.           // we sould have timeout here to allow Tx/Rc flow without huge delays
  2912.           case MsgWaitForMultipleObjects(1, FWaitCompleteIsBusyEvent, False, 50, QS_ALLINPUT) of
  2913.             WAIT_FAILED: Sleep(0); // just in case
  2914.             WAIT_OBJECT_0: begin
  2915.               ReleaseSemaphore(FWaitCompleteIsBusyEvent,1,nil);
  2916.               break; // uWaitComplete thread is finished, so exit loop
  2917.             end;
  2918.             WAIT_TIMEOUT,
  2919.             WAIT_OBJECT_0 + 1: begin
  2920.               // process messages in queue
  2921.               (*
  2922.               while PeekMessage(msg,0,0,0,PM_REMOVE) do begin
  2923.                 DispatchMessage(msg);
  2924.               end;
  2925.               *)
  2926.               Application.ProcessMessages;
  2927.               if FAbort or Application.Terminated then Abort;
  2928.             end;
  2929.           end;
  2930.         end;
  2931.         { END OF TESTING }
  2932.         
  2933.         if IsErrorOccur then begin
  2934.           { phone is out of range ? force disconnect }
  2935.           if FTimedout then
  2936.             ActionConnectionDisconnectExecute(nil);
  2937.           { Obex error NO CARRIER ? force obex abort }  
  2938.           if FObexConnecting and FConnected then begin
  2939.             FObex.ForceAbort; // cancel obex session if needed
  2940.             FObexConnecting := False;
  2941.           end;
  2942.           raise EInOutError.Create(GetLastError);
  2943.         end;
  2944.       finally
  2945.         Free;
  2946.         { Update actions since phone operation has completed }
  2947.         for i := 0 to ActionList1.ActionCount-1 do ActionList1.UpdateAction(ActionList1.Actions[i]);
  2948.         Update;
  2949.       end;
  2950.     except
  2951.       { Clear Watch for OK flag }
  2952.       FWaitingOK := False;
  2953.       FScriptRunning := False;
  2954.       raise;
  2955.     end;
  2956. end;
  2957.  
  2958. procedure TForm1.FlushOK;
  2959. begin
  2960.   if FObex.Connected then ObexDisconnect;
  2961.   TxAndWait(''); // this will not transmit data, but only check for stray OK response.
  2962.   FAbortDetected := FAbortDetected or (FObex.IsAborted and not CoolTrayIcon1.CycleIcons);
  2963.   FObexConnecting := False;
  2964. end;
  2965.  
  2966. (*
  2967. procedure TForm1.TxAndWait(Data, WaitStr: String);
  2968. var
  2969.   i: Integer;
  2970.   CancelObex: boolean;
  2971. begin
  2972.   if FRxBuffer = nil then exit;
  2973.  
  2974.   if WaitStr = '' then begin
  2975.     Debug('[TX] ' + Data);
  2976.  
  2977.     if FConnectionType = 0 then WBtSocket.SendStr(Data + #13)
  2978.     else if FConnectionType = 1 then WIrSocket.SendStr(Data + #13)
  2979.     else VaComm.WriteText(Data + #13); // Serial
  2980.  
  2981.     Exit;
  2982.   end;
  2983.  
  2984.   { Wait for previous command to finish
  2985.   repeat
  2986.     if WaitForSingleObject(FWaitCompleteIsBusyEvent,50) = WAIT_OBJECT_0 then break;
  2987.     Application.ProcessMessages;
  2988.     if Application.Terminated then Abort;
  2989.   until False;
  2990.   {}
  2991.   CancelObex := False;
  2992.   try
  2993.     { Wait for previous command completion, if any }
  2994.     while FBusy or FWaitingOK do WaitComplete;
  2995.  
  2996.     { Set semafor before execution }
  2997.     FBusy := True;
  2998.     try
  2999.       { Send... }
  3000.       Debug('[TX] ' + Data);
  3001.       { Convert if required }
  3002.       if FDoCharConvertion then begin
  3003.         for i := 1 to length(Data) do
  3004.           Data[i] := ConvertCharSet(Data[i], True);
  3005.       end;
  3006.       { Prepare }
  3007.       FRxBuffer.Clear;
  3008.       FWaitStr := WaitStr;
  3009.       FLastCommand := Data;
  3010.       { Check for Obex connect attempt }
  3011.       CancelObex := (AnsiCompareText(WaitStr,'CONNECT') = 0) and
  3012.         (AnsiCompareText(Data,'AT*EOBEX') = 0);
  3013.       if CancelObex then FAlreadyInUseObex := False;
  3014.       { Set Watch for OK flag }
  3015.       FWaitingOK := (FWaitStr = 'OK') or CancelObex;
  3016.       { Reset inactivity timeout }
  3017.       FMSec := GetTickCount + FInactivityTimeout;
  3018.       FTimedout := False;
  3019.       { Execute command }
  3020.       if FConnectionType = 0 then WBtSocket.SendStr(Data + #13)
  3021.       else if FConnectionType = 1 then WIrSocket.SendStr(Data + #13)
  3022.       else VaComm.WriteText(Data + #13); // Serial
  3023.       { Wait for the response }
  3024.       WaitComplete;
  3025.     finally
  3026.       { Ok, clear the semafor, allow next commands
  3027.       ReleaseSemaphore(FWaitCompleteIsBusyEvent,1,nil);
  3028.       {}
  3029.       FBusy := False;
  3030.     end;
  3031.   except
  3032.     { Clear Watch for OK flag }
  3033.     FWaitingOK := False;
  3034.     FScriptRunning := False;
  3035.     if CancelObex and FConnected then
  3036.       FObex.ForceAbort;
  3037.     raise;
  3038.   end;
  3039. end;
  3040.  
  3041. procedure TForm1.WaitComplete;
  3042. var
  3043.   i: integer;
  3044. begin
  3045.   Screen.Cursor := crAppStart;
  3046.   try
  3047.     while (FWaitStr <> '') and (not FTimedout) and (not FAbort) do begin
  3048.       FTimedout := not (GetTickCount < FMSec);
  3049.  
  3050.       if FWaitStr = 'ERROR' then begin
  3051.         FWaitStr := '';
  3052.         Debug('[ERR] ' + FRxBuffer.Text);
  3053.         { Do a silent exception if exiting }
  3054.         if Application.Terminated then Abort
  3055.           else raise Exception.Create('Command return error');
  3056.       end;
  3057.  
  3058.       Application.ProcessMessages;
  3059.     end;
  3060.     
  3061.     if FTimedout then begin
  3062.       ActionConnectionDisconnectExecute(nil);
  3063.       if not IsAutoConnect then Debug('Connection: Wait timeout');
  3064.       raise Exception.Create('Wait timeout');
  3065.     end;
  3066.     if FAbort then begin
  3067.       FAbort := False;
  3068.       FAbortDetected := True;
  3069.       Debug('Connection: Aborted by user');
  3070.       raise Exception.Create('Operation aborted by user');
  3071.     end
  3072.     else
  3073.       FAbortDetected := False;
  3074.   finally
  3075.     Screen.Cursor := crDefault;
  3076.     FWaitingOK := False;
  3077.     FScriptRunning := False;
  3078.     FBusy := False;
  3079.     { Update actions since phone operation has completed }
  3080.     for i := 0 to ActionList1.ActionCount-1 do ActionList1.UpdateAction(ActionList1.Actions[i]);
  3081.     Update;
  3082.   end;
  3083. end;
  3084.  
  3085. { Procedure to flush a possible stray OK printed out after an OBEX session }
  3086. { is closed on certain phones (T310)                                       }
  3087. { Added by bufflig                                                         }
  3088. procedure TForm1.FlushOK;
  3089. Var
  3090.   Timedout     : Boolean;
  3091.   FlushTimeout : Cardinal;
  3092.  
  3093. begin        
  3094.   { Wait for previous command to finish } 
  3095.   while FBusy do WaitComplete;
  3096.   
  3097.   { Check now }
  3098.   FBusy := True;
  3099.   try
  3100.     Screen.Cursor := crAppStart;
  3101.     Debug('Flushing possible stray "OK"...');
  3102.     FlushTimeout := GetTickCount + 500; { Waiting half a second will be enough }
  3103.     Timedout := False;
  3104.     FWaitStr := 'OK';
  3105.     while (FWaitStr <> '') and (not Timedout) and (not FAbort) do begin
  3106.       Timedout := not (GetTickCount < FlushTimeout);
  3107.       Application.ProcessMessages;
  3108.       Sleep(10);
  3109.     end;
  3110.   finally
  3111.     FBusy := False;
  3112.     Screen.Cursor := crDefault;
  3113.   end;
  3114.   if Timedout then
  3115.      Debug('Got timeout flushing OK (no stray "OK")')
  3116.   else
  3117.      Debug('Got the stray "OK" when flushing');
  3118.   FAbortDetected := FAbortDetected or (FObex.IsAborted and not CoolTrayIcon1.CycleIcons);
  3119. end;
  3120. *)
  3121.  
  3122. procedure TForm1.ComPortRxChar(Sender: TObject; Count: Integer);
  3123. var
  3124.   c: char;
  3125.   i: Integer;
  3126.   buffer: String;
  3127.   PStr: PChar;
  3128. begin
  3129.   if FConnectionType = 0 then begin
  3130.     SetLength(buffer, 2048);
  3131.     SetLength(buffer, WBtSocket.Receive(@buffer[1], 2048));
  3132.   end
  3133.   else if FConnectionType = 1 then begin
  3134.     SetLength(buffer, 2048);
  3135.     SetLength(buffer, WIrSocket.Receive(@buffer[1], 2048));
  3136.   end
  3137.   else begin
  3138.     SetLength(buffer, Count);
  3139.     ComPort.ReadStr(buffer, Count);
  3140.   end;
  3141.  
  3142.   for i := 1 to length(buffer) do begin
  3143.     c := buffer[i];
  3144.     if FDoCharConvertion then c := ConvertCharSet(c);
  3145.     if FObex.Connected then FObex.OnRxChar(c)
  3146.     else begin
  3147.       case c of
  3148.         #00:;
  3149.         #10:;
  3150.         #13:
  3151.           begin
  3152.             if length(trim(FMessage)) > 0 then
  3153.             begin
  3154.               PStr := StrNew(PChar(FMessage));
  3155.               PostMessage(Handle, FMA_HANDLEMESSAGE, Integer(PStr), 0);
  3156.             end;
  3157.             FMessage := '';
  3158.           end;
  3159.         else begin
  3160.           FMessage := FMessage + c;
  3161.         end;
  3162.       end;
  3163.  
  3164.       if (FMessage = FWaitStr) and (FMessage <> '') then begin
  3165.         PStr := StrNew(PChar(FMessage));
  3166.         PostMessage(Handle, FMA_HANDLEMESSAGE, Integer(PStr), 0);
  3167.         FMessage := '';
  3168.       end;
  3169.     end;
  3170.   end;
  3171. end;
  3172.  
  3173. procedure TForm1.FormCreate(Sender: TObject);
  3174. var
  3175.   i: integer;
  3176.   sa: TSecurityAttributes;
  3177.   function ShiftColor(Value,Shift: integer): Byte;
  3178.   begin
  3179.     inc(Value,Shift);
  3180.     if Value < 0 then Value := 0;
  3181.     if Value > 255 then Value := 255;
  3182.     Result := Value;
  3183.   end;
  3184. begin
  3185. {$IFNDEF VER150}
  3186.   ThemeManager1 := TThemeManager.Create(Self);
  3187.   ThemeManager1.Options := [toAllowNonClientArea, toAllowControls, toAllowWebContent, toSubclassButtons, toSubclassCheckListbox, toSubclassDBLookup, toSubclassFrame, toSubclassGroupBox, toSubclassPanel, toSubclassTabSheet, toSubclassSpeedButtons, toSubclassStatusBar, toSubclassTrackBar, toSubclassWinControl, toResetMouseCapture, toSetTransparency];
  3188. {$ENDIF}
  3189.   FWaitCompleteEvent := CreateEvent(nil, False, False, nil);
  3190.   FWaitCompleteIsBusyEvent := CreateSemaphore(nil,1,1,PChar('FmaIsBusy'));
  3191.  
  3192.   { Check whether we are the first instance? }
  3193.   sa.nLength := SizeOf(sa);
  3194.   sa.lpSecurityDescriptor := nil;
  3195.   sa.bInheritHandle := True;
  3196.   FFmaMutex := CreateMutex(@sa,False,PChar('Fma_Instance_One_Mutex'));
  3197.   if WaitForSingleObject(FFmaMutex, 5) = WAIT_TIMEOUT then begin
  3198.     FNotFirstInstance := True;
  3199.     { Another instance of Fma is already running }
  3200.     if FNotFirstInstance then begin
  3201.       Application.ShowMainForm := False;
  3202.     end;
  3203.   end;
  3204.  
  3205.   ExePath := ExtractFilePath(Application.ExeName);
  3206.  
  3207.   Caption := Application.Title;
  3208.   Caption := Caption + ' ' + GetBuildVersionDtl;
  3209.   
  3210.   for i := 0 to CoolBar.Bands.Count-1 do begin
  3211.     CoolBar.Bands[i].MinWidth := CoolBar.Bands[i].Control.Constraints.MinWidth;
  3212.     if CoolBar.Bands[i].MinWidth <> 0 then
  3213.       CoolBar.Bands[i].Width := CoolBar.Bands[i].MinWidth;
  3214.   end;
  3215.  
  3216.   with LMDFill1.FillObject.Gradient do begin
  3217.     i := ColorToRGB(clActiveCaption);
  3218.     i := (ShiftColor(i and $FF0000 shr 16, 16) shl 16) or (ShiftColor(i and $FF00 shr 8, 16) shl 8) or ShiftColor(i and $FF, 16);
  3219.     Color := i;
  3220.     i := ColorToRGB(clActiveCaption);
  3221.     i := (ShiftColor(i and $FF0000 shr 16,-64) shl 16) or (ShiftColor(i and $FF00 shr 8,-64) shl 8) or ShiftColor(i and $FF,-64);
  3222.     EndColor := i;
  3223.   end;
  3224.  
  3225.   FKeyInactivityTimeout := 10000;
  3226.  
  3227.   FRxBuffer := TStringList.Create;
  3228.   FNewMessageList := TStringList.Create;
  3229.   FLookupList := TStringList.Create;
  3230.   FFavoriteRecipients := TStringList.Create;
  3231.   FFavoriteCalls := TStringList.Create;
  3232.   FObex := TObex.Create;
  3233.   FObex.debugobex := False;
  3234.  
  3235.   frmMsgView := TfrmMsgView.Create(FramePanel);
  3236.   frmMsgView.Parent := FramePanel;
  3237.   frmMsgView.Align := alClient;
  3238.  
  3239.   frmSIMEdit := TfrmSIMEdit.Create(FramePanel);
  3240.   frmSIMEdit.Parent := FramePanel;
  3241.   frmSIMEdit.Align := alClient;
  3242.  
  3243.   frmInfoView := TfrmInfoView.Create(FramePanel);
  3244.   frmInfoView.Parent := FramePanel;
  3245.   frmInfoView.Align := alClient;
  3246.   frmInfoView.PopupMenu := PopupMenu2;
  3247.   frmInfoView.BigImage.Picture.Assign(CommonBitmaps.Bitmap[1]);
  3248. {$IFDEF VER150}
  3249.   frmInfoView.ParentBackground := False;
  3250. {$ENDIF}
  3251.  
  3252.   frmSyncPhonebook := TfrmSyncPhonebook.Create(FramePanel);
  3253.   frmSyncPhonebook.Parent := FramePanel;
  3254.   frmSyncPhonebook.Align := alClient;
  3255.  
  3256.   frmExplore := TfrmExplore.Create(FramePanel);
  3257.   frmExplore.Parent := FramePanel;
  3258.   frmExplore.Align := alClient;
  3259.  
  3260.   frmEditor := TfrmEditor.Create(FramePanel);
  3261.   frmEditor.Parent := FramePanel;
  3262.   frmEditor.Align := alClient;
  3263.  
  3264.   if not FNotFirstInstance then begin
  3265.     LoadOptions;
  3266.     InitRegistry;
  3267.   end;
  3268.   FormStorage1.Active := False;
  3269. end;
  3270.  
  3271. procedure TForm1.ActionSMSDownloadInboxExecute(Sender: TObject);
  3272. begin
  3273.   RequestConnection;
  3274.   DownloadMessages(FNodeMsgInbox);
  3275. end;
  3276.  
  3277. procedure TForm1.DownloadSMS(msgType: Integer; Node: TtntTreeNode);
  3278. begin
  3279.   try
  3280.     DownloadSMS(msgType, 'SM', Node);
  3281.     DownloadSMS(msgType, 'ME', Node);
  3282.   except
  3283.     Status('Error Downloading SMS');
  3284.   end;
  3285. end;
  3286.  
  3287. procedure TForm1.DownloadSMS(msgType: Integer; memLocation: String; Node: TtntTreeNode);
  3288. var
  3289.   sl: TStrings;
  3290. begin
  3291.   if Node <> nil then
  3292.     sl := Node.Data
  3293.   else
  3294.     if Explorer.Selected = nil then
  3295.       exit
  3296.     else
  3297.       sl := Explorer.Selected.Data;
  3298.   DownloadSMS(msgType,memLocation,sl);
  3299. end;
  3300.  
  3301. procedure TForm1.DownloadSMS(memLocation: String; index: Integer);
  3302. var
  3303.   i, memType: Integer;
  3304.   header, str, sender, who, text, pdu: WideString;
  3305.   KeepInInbox: boolean;
  3306.   sms: Tsms;
  3307.   sl: TStringList;
  3308.   chat: TfrmCharMessage;
  3309. begin
  3310.   if memLocation = 'ME' then memType := 1
  3311.   else memType := 2;
  3312.   Debug('Downloading new message from ' + memLocation + ' at pos ' + IntToStr(index));
  3313.   try
  3314.     TxAndWait('AT+CPMS="' + memLocation + '"'); // select read and delete phonebook
  3315.     TxAndWait('AT+CMGR=' + IntToStr(index));
  3316.     {
  3317.     12:22:50:139 [TX] AT+CMGR=54
  3318.     12:22:50:340 [RX] +CMGR: 0,,24
  3319.     12:22:50:440 [RX] 07911614910910F7040B911614910631F400004060522122140405F4F29C2E03
  3320.     12:22:50:640 [RX] OK
  3321.     }
  3322.     sl := TStringList.Create;
  3323.     try
  3324.       sl.AddStrings(FRxBuffer);
  3325.       for i := 0 to sl.Count - 1 do begin
  3326.         if pos('+CMGR', sl[i]) = 1 then begin
  3327.           header := trim(copy(sl[i], 8, length(sl[i])));
  3328.           pdu := sl[i+1];
  3329.           { TODO: 'header' already contains if the message is 'new' flag }
  3330.           str := IntToStr(memType) + ',' + IntToStr(index) + ',' + header + ',' + pdu + ',,1'; // 1=new
  3331.           // str = '1,54,0,,24,07911614910910F7040B911614910631F400004060522122140405F4F29C2E03,,1'
  3332.           
  3333.           { Extract sender information }
  3334.           sms := Tsms.Create;
  3335.           try
  3336.             try
  3337.               sms.PDU := pdu;
  3338.               who := LookupContact(sms.Number);
  3339.               if who = '' then begin
  3340.                 who := sms.Number;
  3341.                 sender := sms.Number;
  3342.               end
  3343.               else
  3344.                 sender := who + ' [' + sms.Number + ']';
  3345.               text := sms.Text;
  3346.               chat := GetChatWindow(sms.Number);
  3347.             except
  3348.               who := sUnknownNumber;
  3349.               text := '';
  3350.               chat := nil;
  3351.             end;
  3352.  
  3353.             { Notify Chat }
  3354.             if Assigned(chat) then begin
  3355.               chat.Show;
  3356.               chat.BringToFront;
  3357.               chat.AddChatText(who,Text,sms.TimeStamp);
  3358.             end;
  3359.  
  3360.             { Check where to put message }
  3361.             KeepInInbox := True;
  3362.             if IsMoveToArchiveEnabled or Assigned(chat) then begin // always move chat messages to archive and delete them
  3363.               SaveToArchive(pdu); // archive pdu only
  3364.               try
  3365.                 TxAndWait('AT+CMGD=' + IntToStr(index)); // delete from phone
  3366.                 KeepInInbox := False;
  3367.               except
  3368.               end;
  3369.             end;
  3370.             if KeepInInbox then begin
  3371.               TStrings(FNodeMsgInbox.Data).Add(str); // put in inbox
  3372.               UpdateNewMessagesCounter(FNodeMsgInbox);
  3373.             end;
  3374.  
  3375.             { Mark chat messages as read }
  3376.             if Assigned(chat) then
  3377.               if KeepInInbox then
  3378.                 UpdateNewMessagesCounter(FNodeMsgInbox,pdu,True)
  3379.               else
  3380.                 UpdateNewMessagesCounter(FNodeMsgArchive,pdu,True);
  3381.  
  3382.             { Notify user }
  3383.             if FMsgM then
  3384.               if FTextMessageOptions.NoPopup or Assigned(chat) then begin // do not popup chat messages
  3385.                 if not FTextMessageOptions.NoBaloon then begin
  3386.                   { If not Popup, but Baloon, then show msg text in tray icon baloon tooltip }
  3387.                   CoolTrayIcon1.ShowBalloonHint('New message from '+who,Text,bitNone,60);
  3388.                   FLastBaloonMessagePDU := pdu;
  3389.                 end;
  3390.               end
  3391.               else
  3392.                 if Text <> '' then
  3393.                 with TfrmNewMessage.CreateMsg(Sender, Text, FAlphaCompose) do begin
  3394.                   msgLocation := memLocation;
  3395.                   msgIndex := index;
  3396.                   msgPdu := pdu;
  3397.                   msgInInbox := KeepInInbox;
  3398.                 end;
  3399.                 
  3400.             { Notify script }
  3401.             try
  3402.               ScriptEvent('OnNewSMS', [Sender, Text]);;
  3403.             except
  3404.             end;
  3405.           finally
  3406.             sms.Free;
  3407.           end;
  3408.         end;
  3409.       end;
  3410.     finally
  3411.       { Update view }
  3412.       sl.free;
  3413.       ExplorerChange(nil, Explorer.Selected);
  3414.       { Update database }
  3415.       SaveData;
  3416.     end;  
  3417.   except
  3418.     Status('Error downloading new message');
  3419.   end;
  3420. end;
  3421.  
  3422. procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
  3423. begin
  3424.   if not FExit and FMinimize then begin
  3425.     { Just minimize }
  3426.     Action := caNone;
  3427.     Application.Minimize;
  3428.   end
  3429.   else
  3430.     { Exit now... }
  3431.     try
  3432.       SetFrameVisible(''); // Save frame internal changes
  3433.       if FConnected then
  3434.         ActionConnectionDisconnect.Execute // Disconnect and save database changes
  3435.       else
  3436.         DoDisconnect; // Save database changes
  3437.     finally
  3438.       FormStorage1.StoredValue['ActivityLog'] := GetActivityLogWindow.Visible;
  3439.       FormStorage1.StoredValue['SyncLog'] := GetSyncLogWindow.Visible;
  3440.       FormStorage1.StoredValue['DebugLog'] := (frmDebug <> nil) and frmDebug.Visible;
  3441.       FormStorage1.Active := True;
  3442.       FormStorage1.SaveFormPlacement;
  3443.     end;
  3444. end;
  3445.  
  3446. procedure TForm1.ActionContactsDownloadExecute(Sender: TObject);
  3447. var
  3448.   sl: TStrings;
  3449. begin
  3450.   RequestConnection;
  3451.   if frmInfoView.Visible then EBCAState(False);
  3452.   try
  3453.     try
  3454.       if (Explorer.Selected.StateIndex and $0C0000) = $000000 then begin
  3455.         ActionSyncPhonebookExecute(Self);
  3456.       end;
  3457.       if (Explorer.Selected.StateIndex and $0C0000) = $040000 then begin
  3458.         frmSIMEdit.CheckForChanges;
  3459.         TxAndWait('AT+CPBS="SM"');
  3460.         DownloadPhonebook;
  3461.         sl := FNodeContactsSM.data;
  3462.         ParsePhonebookList(sl);
  3463.         RenderContactList(FNodeContactsSM);
  3464.         frmSIMEdit.RenderData;
  3465.       end;
  3466.       { Update database }
  3467.       SaveData;
  3468.     except
  3469.       Status('Error downloading phonebook');
  3470.     end;
  3471.   finally
  3472.     if frmInfoView.Visible then EBCAState(True);
  3473.   end;
  3474. end;
  3475.  
  3476. procedure TForm1.DownloadPhonebook;
  3477. var
  3478.   i: Integer;
  3479.   buffer, start, stop: String;
  3480.   slTmp: TStrings;
  3481.   frmConnect: TfrmConnect;
  3482. begin
  3483.   TxAndWait('AT+CPBR=?');
  3484.  
  3485.   buffer := FRxBuffer.Strings[0];
  3486.   for i := 1 to length(buffer) do begin
  3487.     if IsDelimiter('()-', buffer, i) then buffer[i] := ' ';
  3488.   end;
  3489.  
  3490.   slTmp := TStringList.Create;
  3491.   try
  3492.     slTmp.DelimitedText := buffer;
  3493.     start := slTmp.Strings[1];
  3494.     stop := slTmp.Strings[2];
  3495.   finally
  3496.     slTmp.Free;
  3497.   end;
  3498.  
  3499.   Status('Downloading phonebook (' + start + '-' + stop + ')...');
  3500.   frmConnect := GetProgressDialog;
  3501.   try
  3502.     if CanShowProgress then
  3503.       frmConnect.ShowProgress(FProgressLongOnly);
  3504.     frmConnect.SetDescr('Downloading phonebook');
  3505.     TxAndWait('AT+CPBR=' + start + ',' + stop);
  3506.     Status('Download completed');
  3507.   finally
  3508.     FreeProgressDialog;
  3509.   end;
  3510. end;
  3511.  
  3512. procedure TForm1.ParsePhonebookList(var sl: TStrings);
  3513. var
  3514.   s: WideString;
  3515.   i, position: Integer;
  3516.   slTmp: TStrings;
  3517.   Name, Number, NumType: String;
  3518.   ml: TStringList;
  3519. begin
  3520.   sl.Clear;
  3521.   ml := TStringList.Create;
  3522.   ml.AddStrings(FRxBuffer);
  3523.   try
  3524.     for i := 0 to ml.Count - 1 do begin
  3525.       if pos('+CPBR', ml[i]) = 1 then begin
  3526.         slTmp := TStringList.Create;
  3527.         try
  3528.           s := ml[i];
  3529.           Delete(s,1,7);
  3530.           if FUseUTF8 then s := UTF8Decode(s);
  3531.           position := StrToInt(GetFirstToken(s));
  3532.           Number := GetFirstToken(s);
  3533.           NumType := GetFirstToken(s);
  3534.           Name := GetFirstToken(s);
  3535.  
  3536.           if (NumType = '145') and (Number[1] <> '+') then
  3537.             Number := '+' + Number;
  3538.           {
  3539.           slTmp.DelimitedText := s;
  3540.           // TODO: hadle names with quotes inside!!
  3541.           position := StrToInt(slTmp.Strings[1]);
  3542.           Number := slTmp.Strings[2];
  3543.           Name := slTmp.Strings[4];
  3544.  
  3545.           if (slTmp.Strings[3] = '145') and (Number[1] <> '+') then
  3546.             Number := '+' + Number;
  3547.           }
  3548.         finally
  3549.           slTmp.Free;
  3550.         end;
  3551.         sl.Add('"' + Name + '",' + Number + ',' + IntToStr(position) + ',3'); // 3 = not modified (new) item
  3552.       end;
  3553.     end;
  3554.   finally
  3555.     ml.Free;
  3556.     TStringList(sl).Sort;
  3557.   end;
  3558. end;
  3559.  
  3560. procedure TForm1.RenderContactList;
  3561. begin
  3562.   Explorer.Items.BeginUpdate;
  3563.   try
  3564.     RenderContactList(FNodeContactsME);
  3565.     RenderContactList(FNodeContactsSM);
  3566.   finally
  3567.     Explorer.Items.EndUpdate;
  3568.   end;  
  3569. end;
  3570.  
  3571. procedure TForm1.RenderContactList(var rootNode: TtntTreeNode);
  3572. var
  3573.   nameNode, numNode: TtntTreeNode;
  3574.   i, j: Integer;
  3575.   sl, tracker: TStrings;
  3576.   s, Name, NumType: WideString;
  3577.   Number, position, partialNumber: String;
  3578. begin
  3579.   { Clear LookupContact cache }
  3580.   FLookupList.Clear;
  3581.   { Now render list }
  3582.   Explorer.Items.BeginUpdate;
  3583.   try
  3584.     sl := rootNode.Data;
  3585.     rootNode.DeleteChildren;
  3586.  
  3587.     nameNode := nil;
  3588.     tracker := TStringList.Create;
  3589.     try
  3590.       i := 0;
  3591.       while i < sl.Count do begin
  3592.         try
  3593.           s := sl.Strings[i];
  3594.           while (not EvenQuotes(s)) and (i < sl.Count - 2) do begin
  3595.             Inc(i);
  3596.             s := s + #13#10 + sl.Strings[i];
  3597.           end;
  3598.  
  3599.           Name := GetFirstToken(s);
  3600.           Number := GetFirstToken(s);
  3601.           position := GetFirstToken(s);
  3602.  
  3603.           ExtractName(Name, NumType);
  3604.  
  3605.           partialNumber := GetPartialNumber(Number);
  3606.           FLookupList.Add(partialNumber + '=' + Name);
  3607.  
  3608.           if tracker.IndexOf(Name) = -1 then begin
  3609.             nameNode := Explorer.Items.AddChild(rootNode, Name);
  3610.             nameNode.ImageIndex := 8;
  3611.             tracker.Add(Name);
  3612.           end
  3613.           else begin
  3614.             for j := rootNode.AbsoluteIndex to Explorer.Items.Count - 1 do begin
  3615.               if Explorer.Items[j].Text = Name then begin
  3616.                 nameNode := Explorer.Items[j];
  3617.                 break;
  3618.               end;
  3619.             end;
  3620.           end;
  3621.  
  3622.          { Each number's StateIndex contains its position in phonebook }
  3623.           numNode := Explorer.Items.AddChild(nameNode, Number);
  3624.           numNode.StateIndex := StrToInt(position);
  3625.  
  3626.           if NumType = 'H' then numNode.ImageIndex := 9
  3627.           else if NumType = 'M' then numNode.ImageIndex := 10
  3628.           else if NumType = 'W' then numNode.ImageIndex := 11
  3629.           else if NumType = 'F' then numNode.ImageIndex := 12
  3630.           else numNode.ImageIndex := 13;
  3631.         except
  3632.           on E: Exception do
  3633.             Debug('CONTACTS DB ERROR (' + E.Message + '): '+s);
  3634.         end;
  3635.  
  3636.         Inc(i);
  3637.       end;
  3638.     finally
  3639.       tracker.Free;
  3640.     end;
  3641.   finally
  3642.     RootNode.AlphaSort;
  3643.     Explorer.Items.EndUpdate;
  3644.     { Update explorer default view if nessesery }
  3645.     if (Explorer.Selected = rootNode) and frmExplore.Visible then
  3646.       frmExplore.RootNode := rootNode;
  3647.   end;
  3648. end;
  3649.  
  3650. procedure TForm1.ContactListGetSelectedIndex(Sender: TObject;
  3651.   Node: TTreeNode);
  3652. begin
  3653.   Node.SelectedIndex := Node.ImageIndex;
  3654. end;
  3655.  
  3656. function TForm1.LookupContact(Number: String; DefaultName: string): String;
  3657. var
  3658.   partialNumber: String;
  3659. begin
  3660.   Result := '';
  3661.   { remove any name suplyed }
  3662.   Number := ExtractNumber(Number);
  3663.   { do lookup in ME if possible }
  3664.   if not FStartupOptions.NoIRMC then
  3665.     Result := frmSyncPhonebook.FindContact(Number);
  3666.   { do lookup in SM if not found }
  3667.   if Result = '' then begin
  3668.     partialNumber := GetPartialNumber(Number);
  3669.     if FLookupList.IndexOfName(partialNumber) <> -1 then
  3670.       Result := FLookupList.Values[partialNumber]
  3671.     else
  3672.       FLookupList.Add(partialNumber + '=');
  3673.   end;
  3674.   { return default name if not found }
  3675.   if Result = '' then Result := DefaultName;
  3676. end;
  3677.  
  3678. procedure TForm1.ExplorerGetSelectedIndex(Sender: TObject;
  3679.   Node: TTreeNode);
  3680. begin
  3681.   Node.SelectedIndex := Node.ImageIndex;
  3682. end;
  3683.  
  3684. procedure TForm1.ExplorerChange(Sender: TObject; Node: TTreeNode);
  3685. begin
  3686.   if Node <> nil then begin
  3687.     if Node <> FNodeContactsME then ActionConnectionDownload.Hint := 'Refresh Data'
  3688.       else ActionConnectionDownload.Hint := 'Synchronize Phonebook';
  3689.     if ((Node.StateIndex and $F00000) = $200000) and ((Node.StateIndex and $0F0000) <> 0) then begin // SMS
  3690.       if Node.Data <> nil then frmMsgView.RenderListView(TStrings(Node.Data));
  3691.       SetFrameVisible('MSG');
  3692.     end
  3693.     else if (Node.StateIndex and $F00000) = $100000 then begin // Contacts
  3694.       //SetActionState(ActionConnectionDownload, True);
  3695.     end
  3696.     else if (Node.StateIndex and $F00000) = $500000 then begin // Files
  3697.       //SetActionState(ActionConnectionDownload, True);
  3698.       SetFrameVisible('EXPLORE');
  3699.     end
  3700.     else if (Node.StateIndex and $F00000) = $700000 then begin // Profiles
  3701.       //SetActionState(ActionConnectionDownload, True);
  3702.       SetFrameVisible('EXPLORE');
  3703.     end
  3704.     else if (Node.StateIndex and $F00000) = $800000 then begin // Groups
  3705.       //SetActionState(ActionConnectionDownload, True);
  3706.       SetFrameVisible('EXPLORE');
  3707.     end
  3708.     else if Node <> Explorer.Items.GetFirstNode then begin // Common Explore
  3709.       SetFrameVisible('EXPLORE');
  3710.     end
  3711.     else if (Node = Explorer.Items.GetFirstNode) then begin // Root
  3712.       if PanelTest.Enabled then
  3713.         SetFrameVisible('')
  3714.       else 
  3715.         SetFrameVisible('INFO');
  3716.     end;
  3717.     if Node = FNodeContactsSM then begin
  3718.       SetFrameVisible('SIM');
  3719.       if not frmSIMEdit.IsRendered then frmSIMEdit.RenderData;
  3720.     end else
  3721.     if Node = FNodeContactsME then begin
  3722.       if FStartupOptions.NoIRMC then begin
  3723.         SetFrameVisible('SIM');
  3724.         if not frmSIMEdit.IsRendered then frmSIMEdit.RenderData;
  3725.       end
  3726.       else
  3727.         SetFrameVisible('PHONE');
  3728.     end else
  3729.     if Node = FNodeScripts then begin
  3730.       SetFrameVisible('SCRIPT');
  3731.     end;
  3732.   end
  3733.   else
  3734.     SetFrameVisible('');
  3735.   if Explorer.Selected <> nil then begin
  3736.     if Explorer.Selected = Explorer.Items.GetFirstNode then begin
  3737.       lblCurrentPage.Caption := 'Fma Today';
  3738.       lblCurrentPageDtls.Left := lblCurrentPage.Left*2 + lblCurrentPage.Width;
  3739.       lblCurrentPageDtls.Caption := Explorer.Selected.Text;
  3740.       lblCurrentPageDtls.Visible := True;
  3741.     end
  3742.     else begin
  3743.       lblCurrentPage.Caption := Explorer.Selected.Text;
  3744.       lblCurrentPageDtls.Visible := False;
  3745.     end;
  3746.   end;
  3747.   {
  3748.   Remove1.Visible := (Explorer.Selected <> nil) and (Explorer.Selected.Parent <> nil) and
  3749.     ((Explorer.Selected.Parent.Parent = FNodeGroups) or (Explorer.Selected.Parent.Parent = FNodeObex));
  3750.   }
  3751.   EBCAState(frmInfoView.Visible);
  3752.   { Reenabled Key Monitoring if needed since EBCAState might disable it }
  3753.   if FConnected and not FObex.Connected and not FObexConnecting and not frmInfoView.Visible and
  3754.     FKeyMonitoring and FEBCAKeyMonStopped then TxAndWait('AT+CMER=3,2');
  3755. end;
  3756.  
  3757. procedure TForm1.Debug(str: String; PrefixTimestamp: boolean);
  3758. begin
  3759.   DoLog(frmDebug,str,PrefixTimestamp);
  3760.   if (Pos('[RX]',str) = 0) and (Pos('[TX]',str) = 0) and (Pos('ERROR:',str) = 0) and
  3761.     (Pos('[ERR]',str) = 0) and (Pos('Exception:',str) = 0) then
  3762.     DoLog(GetActivityLogWindow,str,PrefixTimestamp);
  3763. end;
  3764.  
  3765. procedure TForm1.ActionConnectionDownloadExecute(Sender: TObject);
  3766. var
  3767.   id: Integer;
  3768. begin
  3769.   RequestConnection;
  3770.   id := Explorer.Selected.StateIndex;
  3771.   // Contacts
  3772.   if (id and $F00000) = $100000 then ActionContactsDownloadExecute(Self);
  3773.   // Messages
  3774.   if (id and $F00000) = $200000 then
  3775.     if (id and $0F0000) = 0 then
  3776.       DownloadAllMessages // this is Text Messages root folder, so download all of them :)                     
  3777.     else
  3778.       DownloadMessages(Explorer.Selected);; // this will work for both Inbox and Send Items
  3779.   // Calls
  3780.   if (id and $F00000) = $400000 then
  3781.     case (id and $0F0000) shr 16 of
  3782.       0: InitCalls;
  3783.       1: InitCalls(FNodeCallsIn);
  3784.       2: InitCalls(FNodeCallsOut);
  3785.       3: InitCalls(FNodeCallsMissed);
  3786.     end;
  3787.   // Organizer
  3788.   if (id and $F00000) = $300000 then
  3789.     case (id and $0F0000) shr 16 of
  3790.       0: ;
  3791.       1: ;
  3792.       2: InitBookmarks;
  3793.       3: ;
  3794.       4: ;
  3795.     end;
  3796.   // Other
  3797.   if (id and $F00000) = $500000 then InitObexFolders;
  3798.   if (id and $F00000) = $700000 then InitProfile;
  3799.   if (id and $F00000) = $800000 then InitGroups;
  3800.   // Update view
  3801.   ExplorerChange(nil,Explorer.Selected);
  3802.   // Update database
  3803.   // Only if not Messages, Calls or Groups since they will do it anyway
  3804.   if not ((id and $F00000 shr 20) in [$2,$4,$8]) then SaveData;
  3805. end;
  3806.  
  3807. procedure TForm1.Status(str: String; UpdateDebugLog: boolean);
  3808. begin
  3809.   if UpdateDebugLog and (str <> '') then
  3810.     Debug(str);
  3811.   StatusBar.Panels[4].Text := str;
  3812.   StatusBar.Update;
  3813. end;
  3814.  
  3815. procedure TForm1.ActionSMSArchiveMsgExecute(Sender: TObject);
  3816. var
  3817.   index, i, location: Integer;
  3818.   node: PVirtualNode;
  3819.   item: PListData;
  3820. begin
  3821.   Status('Archiving ' + IntToStr(frmMsgView.ListMsg.SelectedCount) + ' item(s)...');
  3822.  
  3823.   node := frmMsgView.ListMsg.GetFirst;
  3824.   Repeat
  3825.     if frmMsgView.ListMsg.Selected[node] then begin
  3826.       item := frmMsgView.ListMsg.GetNodeData(node);
  3827.       index := item.StateIndex and $FFFF;
  3828.       location := ((item.StateIndex and $0C0000) shr 18) + 1;
  3829.  
  3830.       for i := 0 to TStrings(Explorer.Selected.Data).Count - 1 do begin
  3831.         if GetToken(TStrings(Explorer.Selected.Data).Strings[i], 1) = IntToStr(index) then begin
  3832.           if GetToken(TStrings(Explorer.Selected.Data).Strings[i], 0) = IntToStr(location) then begin
  3833.             SaveMsgToFolder(FNodeMsgArchive,GetToken(TStrings(Explorer.Selected.Data)[i],5),True,False);
  3834.             //SaveToArchive(GetToken(TStrings(Explorer.Selected.Data)[i], 5));
  3835.             break;
  3836.           end;
  3837.         end;
  3838.       end;
  3839.     end;
  3840.     node := frmMsgView.ListMsg.GetNext(node);
  3841.   Until node = nil;
  3842.   Status('Messages stored in Archive');
  3843.   { Update database }
  3844.   SaveData;
  3845. end;
  3846.  
  3847. procedure TForm1.ActionSelectAllExecute(Sender: TObject);
  3848. begin
  3849.   if frmMsgView.Visible then
  3850.     frmMsgView.ListMsg.SelectAll(false);
  3851.   if frmSyncPhonebook.Visible then
  3852.     frmSyncPhonebook.ListContacts.SelectAll(false);
  3853.   if frmSIMEdit.Visible then
  3854.     frmSIMEdit.ListNumbers.SelectAll(false);
  3855.   if frmExplore.Visible then
  3856.     frmExplore.ListItems.SelectAll(false);
  3857.   if frmEditor.Visible then
  3858.     frmEditor.Script.SelectAll;
  3859. end;
  3860.  
  3861. function TForm1.DeleteSMS(index: Integer; memType: String): Boolean;
  3862. begin
  3863.   RequestConnection;
  3864.   try
  3865.     TxAndWait('AT+CPMS="' + memType + '"');
  3866.     TxAndWait('AT+CMGD=' + IntToStr(index));
  3867.     Result := True;
  3868.   except
  3869.     raise Exception.Create('Delete failed');
  3870.   end;
  3871. end;
  3872.  
  3873. procedure TForm1.ActionDeleteExecute(Sender: TObject);
  3874. begin
  3875.   if frmMsgView.Visible and (frmMsgView.ListMsg.Focused) then begin
  3876.     frmMsgView.btnDELClick(nil);
  3877.   end
  3878.   else if frmSyncPhonebook.Visible and frmSyncPhonebook.ListContacts.Focused then begin
  3879.     frmSyncPhonebook.btnDELClick(nil);
  3880.   end
  3881.   else if frmSIMEdit.Visible and frmSIMEdit.ListNumbers.Focused then begin
  3882.     frmSIMEdit.btnDELClick(nil);
  3883.   end
  3884.   else if frmExplore.Visible and frmExplore.ListItems.Focused then begin
  3885.     if (Explorer.Selected.Parent = FNodeGroups) or (Explorer.Selected.Parent = FNodeObex) then
  3886.       DoRemoveGroupMemberOrFile;
  3887.     if (Explorer.Selected = FNodeBookmarks) then
  3888.       DoRemoveBookmark;
  3889.     if (Explorer.Selected = FNodeGroups) then
  3890.       { check for DoRemoveGroupMemberOrFile should be before DoRemoveGroup }
  3891.       DoRemoveGroup;
  3892.   end
  3893.   else if frmEditor.Visible and frmEditor.Script.Focused then
  3894.     frmEditor.Script.SelText := '';
  3895. end;
  3896.  
  3897. procedure TForm1.ActionSMSMoveMsgToArchiveExecute(Sender: TObject);
  3898. begin
  3899.   ActionSMSArchiveMsg.Execute;
  3900.   ActionDelete.Execute;
  3901. end;
  3902.  
  3903. procedure TForm1.SentMessage(UDHI: String; msg, destNo: WideString; reqReply,
  3904.   Flash: Boolean; StatusReq:Boolean; dcs: Integer; SaveDraft: boolean);
  3905. var
  3906.   sms: TSMS;
  3907.   pdu,who: String;
  3908. begin
  3909.   sms := TSMS.Create;
  3910.   try
  3911.     who := LookupContact(destNo);
  3912.     if who = '' then who := destNo;
  3913.     sms.Text := msg;
  3914.     sms.Number := destNo;
  3915.     sms.RequestReply := reqReply;
  3916.     sms.FlashSMS := Flash;
  3917.     sms.StatusRequest := StatusReq;
  3918.     sms.UDHI := UDHI;
  3919.     sms.dcs := dcs;
  3920.     pdu := sms.PDU;
  3921.     if SaveDraft then begin
  3922.       SaveMsgToFolder(FNodeMsgDrafts,pdu,True);
  3923.       Status('Message saved in Drafts');
  3924.     end
  3925.     else begin
  3926.       { Move message from Drafts (if any) to Outbox folder }
  3927.       SaveMsgToFolder(FNodeMsgOutbox,pdu,True);
  3928.       DelMsgFromFolder(FNodeMsgDrafts,pdu);
  3929.       Status('Message stored in Outbox');
  3930.     end;
  3931.   finally
  3932.     sms.Free;
  3933.   end;
  3934. end;
  3935.  
  3936. procedure TForm1.ActionSMSNewMsgExecute(Sender: TObject);
  3937. begin
  3938.   with frmMessageContact do begin
  3939.     AlphaBlendValue := FAlphaCompose;
  3940.     Show;
  3941.     Clear;
  3942.     Edit1.SetFocus;
  3943.   end;
  3944. end;
  3945.  
  3946. procedure TForm1.ExtractName(var Name, numType: WideString);
  3947. begin
  3948.   if copy(Name, length(Name) - 1, 1) = '/' then begin
  3949.     numType := copy(Name, length(Name), 1);
  3950.     Name := copy(Name, 1, length(Name) - 2);
  3951.   end
  3952.   else numType := 'O';
  3953. end;
  3954.  
  3955. procedure TForm1.SaveToArchive(PDU: String; OverwriteOld: boolean);
  3956. begin
  3957.   SaveMsgToFolder(FNodeMsgArchive,PDU,OverwriteOld);
  3958. end;
  3959.  
  3960. procedure TForm1.SetActionState(act: TAction; state: Boolean);
  3961. begin
  3962.   act.Enabled := state;
  3963. //  act.Visible := state;
  3964. end;
  3965.  
  3966. procedure TForm1.ActionContactsNewMsgExecute(Sender: TObject);
  3967. var
  3968.   Number: string;
  3969. begin
  3970.   Number := LocateSelContactNumber;
  3971.   if Number <> '' then begin
  3972.     ActionSMSNewMsg.Execute;
  3973.     frmMessageContact.AddRecipient(Number);
  3974.     frmMessageContact.Memo.SetFocus;
  3975.   end;
  3976. end;
  3977.  
  3978. procedure TForm1.ActionSMSReplyMsgExecute(Sender: TObject);
  3979. var
  3980.   node: PVirtualNode;
  3981.   item: PListData;
  3982. begin
  3983.   try
  3984.     node := frmMsgView.ListMsg.FocusedNode;
  3985.     if Assigned(node) then
  3986.       item := frmMsgView.ListMsg.GetNodeData(node)
  3987.     else
  3988.       item := nil;
  3989.   except
  3990.     exit;
  3991.   end;
  3992.   if item <> nil then begin
  3993.     ActionSMSNewMsg.Execute;
  3994.     frmMessageContact.AddRecipient(item.from);
  3995.     frmMessageContact.Memo.SetFocus;
  3996.   end;
  3997. end;
  3998.  
  3999. procedure TForm1.ActionSMSForwardMsgExecute(Sender: TObject);
  4000. var
  4001.   node: PVirtualNode;
  4002.   item: PListData;
  4003. begin
  4004.   try
  4005.     node := frmMsgView.ListMsg.FocusedNode;
  4006.     if Assigned(node) then
  4007.       item := frmMsgView.ListMsg.GetNodeData(node)
  4008.     else
  4009.       item := nil;
  4010.   except
  4011.     exit;
  4012.   end;
  4013.   if item <> nil then begin
  4014.     ActionSMSNewMsg.Execute;
  4015.     frmMessageContact.Memo.Text := '';
  4016.     frmMessageContact.Memo.Text := item.msg;
  4017.     frmMessageContact.Memo.SelStart := Length(item.msg);
  4018.   end;
  4019. end;
  4020.  
  4021. procedure TForm1.ActionConnectionToggleExecute(Sender: TObject);
  4022. begin
  4023.   if FConnected then
  4024.     ActionConnectionDisconnect.Execute
  4025.   else
  4026.     ActionConnectionConnect.Execute;
  4027. end;
  4028.  
  4029. procedure TForm1.ActionContactsVoiceCallExecute(Sender: TObject);
  4030. var
  4031.   Number: string;
  4032. begin
  4033.   if (frmCalling <> nil) and frmCalling.IsIncoming and frmCalling.IsCalling and not frmCalling.IsTalking then
  4034.     { Incomming Call in progress, so pick up it }
  4035.     frmCalling.AnswerButton.Click
  4036.   else begin
  4037.     { No active call, so create a new outgoing one }
  4038.     if IsContactNumberSelected then 
  4039.       Number := LocateSelContactNumber
  4040.     else
  4041.       Number := '';
  4042.     frmCallContact.AlphaBlendValue := FAlphaCall;
  4043.     frmCallContact.Show;
  4044.     frmCallContact.AddRecipient(Number);
  4045.   end;
  4046. end;
  4047.  
  4048. procedure TForm1.HandleEMIV(AMsg: String);
  4049. var
  4050.   str: String;
  4051. begin
  4052.   str := copy(AMsg, 8, length(AMsg));
  4053.   ScriptEvent('OnMusicMute', [str]);
  4054. end;
  4055.  
  4056. procedure TForm1.HandleEAMI(AMsg: String);
  4057. var
  4058.   position: Integer;
  4059.   Event, buf, value: String;
  4060.   dlgType: Integer;
  4061. begin
  4062.   dlgType := -1;
  4063.   buf := copy(AMsg, 8, length(AMsg));
  4064.  
  4065.   if pos('*EAMI', AMsg) = 1 then begin
  4066.     try
  4067.       position := StrToInt(buf);
  4068.     except
  4069.       position := 0; //on EConvertError do exit;
  4070.     end;
  4071.   end
  4072.   else begin // EAII
  4073.     dlgType := StrToInt(GetToken(buf, 0));
  4074.     case dlgType of
  4075.      0,1,14: position := 0; // 0 - Back/timeout, 1,14 - MsgBox - Information
  4076.      2,3,4,7,11,
  4077.      15: begin
  4078.            position := 0;
  4079.            value := GetToken(buf, 1);
  4080.          end;
  4081.       5: begin
  4082.            try
  4083.              position := StrToInt(GetToken(buf, 1));
  4084.            except
  4085.              position := 0;
  4086.            end;
  4087.          end;
  4088.       else
  4089.         Exit;
  4090.     end;
  4091.   end;
  4092.  
  4093.   if position = 0 then Event := FAccessoriesMenu.FBack
  4094.   else begin
  4095.     Event := FAccessoriesMenu.FEventList.Strings[position-1];
  4096.     FAccessoriesMenu.FSelected := position;
  4097.   end;
  4098.  
  4099.   { Use scheduled (delayed) execution of script events }
  4100.   case dlgType of
  4101.    -1,0,1,14: if Event <> '' then ScheduleScriptEvent(Event, []);
  4102.            5: if Event <> '' then ScheduleScriptEvent(Event, [position]);
  4103.     2,3,7,11: if FAccessoriesMenu.FGeneralEvent <> '' then ScheduleScriptEvent(FAccessoriesMenu.FGeneralEvent, [value]);
  4104.            4: if FAccessoriesMenu.FGeneralEvent <> '' then ScheduleScriptEvent(FAccessoriesMenu.FGeneralEvent, [value, 1]);
  4105.           15: if FAccessoriesMenu.FGeneralEvent <> '' then ScheduleScriptEvent(FAccessoriesMenu.FGeneralEvent, [value, 0]);
  4106.   end;
  4107. end;
  4108.  
  4109. procedure TForm1.HandleECAV(AMsg: String);
  4110. var
  4111.   timestamp: String;
  4112.   str,missed: String;
  4113.   ccstatus: Integer;
  4114.   IsAutoAnswer: boolean; // When using headset
  4115. const
  4116.   ccsDesc: array[0..7] of string = ('Idle', 'Calling', 'Connecting', 'Active', 'Hold', 'Waiting', 'Alerting', 'Busy');
  4117. begin
  4118.   DateTimeToString(timestamp, 'yyyy"/"mm"/"dd,hh":"nn', now);
  4119.  
  4120.   { TODO: Handle Second incoming call }
  4121.   { TODO: Handle frmCalling <> nil }
  4122.  
  4123.   if not frmCalling.IsCalling and not frmCalling.Visible then begin
  4124.     { Setup popup window, but show it only if specified }
  4125.     frmCalling.CreateCall('',FCallM,FAlphaCall);
  4126.   end;
  4127.  
  4128.   str := copy(AMsg, 8, length(AMsg));
  4129.   if pos('*ECAV', AMsg) = 1 then begin
  4130.     ccstatus := StrToInt(GetToken(str, 1));
  4131.  
  4132.     { TODO: Handle calling while talking }
  4133.     if (ccstatus = 1) and not frmCalling.IsTalking then begin
  4134.       { Outgoing call }
  4135.       frmCalling.Caption := 'Calling...';
  4136.       frmCalling.lbNumber.Caption := GetToken(str, 5);
  4137.       if (GetToken(str, 6) = '145') and (frmCalling.lbNumber.Caption <> '') and (frmCalling.lbNumber.Caption[1] <> '+') then
  4138.         frmCalling.lbNumber.Caption := '+' + frmCalling.lbNumber.Caption;
  4139.       if frmCalling.lbAlpha.Caption = sUnknownNumber then
  4140.         frmCalling.lbAlpha.Caption := sUnknownContact;
  4141.       frmCalling.AnswerButton.Visible := False;
  4142.       frmCalling.HeadsetButton.Visible := False;
  4143.       frmCalling.HandupButton.Visible := True;
  4144.       if frmCalling.Visible then
  4145.         frmCalling.HandupButton.SetFocus;
  4146.       frmCalling.IsIncoming := False;
  4147.       frmCalling.IsCalling := True;
  4148.       frmCalling.IsBusy := False;
  4149.       frmCalling.DoPersonalize;
  4150.       { Start outgoing ringing, we'll use a timer }
  4151.       frmCalling.TimeTimer.Enabled := True;
  4152.       Status('Dialing...');
  4153.       { Add to explorer outgoing call }
  4154.       AddCall(FNodeCallsOut,ContactNumberByTel(frmCalling.lbNumber.Caption),timestamp,True);
  4155.       { Update view }
  4156.       if frmInfoView.Visible then frmInfoView.UpdateWelcomePage(True)
  4157.         else ExplorerChange(nil,Explorer.Selected);
  4158.     end;
  4159.  
  4160.     if ccstatus = 7 then begin
  4161.       frmCalling.IsBusy := True;
  4162.     end;
  4163.  
  4164.     { TODO: Handle second call while talking }
  4165.     if (ccstatus = 6) and not frmCalling.IsTalking then begin
  4166.       { Incoming call }
  4167.       frmCalling.Caption := 'Incoming Call...';
  4168.       frmCalling.lbNumber.Caption := GetToken(str, 5);
  4169.       if (GetToken(str, 6) = '145') and (frmCalling.lbNumber.Caption <> '') and (frmCalling.lbNumber.Caption[1] <> '+') then
  4170.         frmCalling.lbNumber.Caption := '+' + frmCalling.lbNumber.Caption;
  4171.       frmCalling.HeadsetButton.Visible := True;
  4172.       frmCalling.HandupButton.Visible := True;
  4173.       frmCalling.AnswerButton.Visible := True;
  4174.       if frmCalling.Visible then
  4175.         frmCalling.AnswerButton.SetFocus;
  4176.       frmCalling.IsIncoming := True;
  4177.       frmCalling.IsCalling := True;
  4178.       frmCalling.DoPersonalize;
  4179.       Status('Ringing...');
  4180.     end;
  4181.  
  4182.     if ccstatus = 3 then begin
  4183.       { Call activated }
  4184.       IsAutoAnswer := frmCalling.AnswerButton.Enabled and frmCalling.IsIncoming; // Using BT Audio Gateway?
  4185.       frmCalling.StopPersonalize(False);
  4186.       frmCalling.AnswerButton.Enabled := False;
  4187.       frmCalling.HeadsetButton.Visible := False;
  4188.       frmCalling.HandupButton.Visible := True;
  4189.       if frmCalling.Visible and (frmCalling.ActiveControl <> frmCalling.Memo) then
  4190.         frmCalling.HandupButton.SetFocus;
  4191.       { Active call, so mark it as processed, i.e. not missed one }
  4192.       frmCalling.IsTalking := True;
  4193.       Status('Talking...');
  4194.       if frmCalling.IsIncoming then begin
  4195.         { Add to explorer incoming call }
  4196.         AddCall(FNodeCallsIn,ContactNumberByTel(frmCalling.lbNumber.Caption),timestamp,True);
  4197.         { Update view }
  4198.         if frmInfoView.Visible then frmInfoView.UpdateWelcomePage(True)
  4199.           else ExplorerChange(nil,Explorer.Selected);
  4200.       end;
  4201.     end
  4202.     else
  4203.       IsAutoAnswer := False;
  4204.  
  4205.     if ccstatus = 0 then
  4206.       { Call ended }
  4207.       try
  4208.         CoolTrayIcon1.HideBalloonHint; // hide calling baloon
  4209.         if frmCalling.IsIncoming and not frmCalling.IsTalking then begin
  4210.           { Add to explorer missed calls }
  4211.           str := ContactNumberByTel(frmCalling.lbNumber.Caption);
  4212.           AddCall(FNodeCallsMissed,str,timestamp,True);
  4213.           { Add to Recent missed calls counter }
  4214.           if frmMissedCalls <> nil then
  4215.             frmMissedCalls.RecentMissedCalls := frmMissedCalls.RecentMissedCalls + 1;
  4216.           { Update view }
  4217.           if frmInfoView.Visible then frmInfoView.UpdateWelcomePage(True)
  4218.             else ExplorerChange(nil,Explorer.Selected);
  4219.  
  4220.           { Schedule command to remove Popup window in phone }
  4221.           FClearPhoneMessage := True;
  4222.           Debug(missed);
  4223.           str := 'You have new missed call';
  4224.           if frmMissedCalls <> nil then
  4225.             if frmMissedCalls.RecentMissedCalls > 1 then
  4226.               str := str + 's';
  4227.           ShowBaloonInfo(str+'.',60);
  4228.         end;
  4229.       finally
  4230.         Debug('Last call duration: '+frmCalling.lblTime.Caption);
  4231.         Status('Call ended ('+frmCalling.lblTime.Caption+')');
  4232.         frmCalling.IsCalling := False;
  4233.         frmCalling.IsTalking := False;
  4234.         frmCalling.Close;
  4235.       end
  4236.     else begin
  4237.       frmCalling.Caption := ccsDesc[ccstatus];
  4238.       if (ccstatus = 3) and IsAutoAnswer then
  4239.         frmCalling.Caption := frmCalling.Caption + ' (Auto-answered)';
  4240.     end;
  4241.     FLastECAVStatus := ccstatus;
  4242.   end;
  4243.  
  4244.   { Get Caller ID }
  4245.   if (pos('*EOLP', AMsg) = 1) or (pos('*ELIP', AMsg) = 1) then begin
  4246.     if FUseUTF8 then
  4247.       str := UTF8Decode(GetToken(str, 0))
  4248.     else
  4249.       str := GetToken(str, 0);
  4250.     { TODO: Handle miltiple calls }
  4251.     if not frmCalling.IsTalking then begin
  4252.       frmCalling.lbAlpha.Caption := str;
  4253.       //frmCalling.DoPersonalize;
  4254.     end;
  4255.   end;
  4256.   
  4257.   { Notify script }
  4258.   if FCallM then
  4259.     ScriptEvent('OnCall', [frmCalling.Caption, frmCalling.lbAlpha.Caption, frmCalling.lbNumber.Caption]);
  4260. end;
  4261.  
  4262. procedure TForm1.HandleRinging;
  4263. begin
  4264.   if (frmCalling <> nil) and not frmCalling.IsTalking then begin
  4265.     if frmCalling.Visible or not FCallM then begin
  4266.       frmCalling.DoPersonalize;
  4267.       if frmCalling.IsPersonalized then
  4268.         Status(frmCalling.lbAlpha.Caption+' is calling...')
  4269.       else
  4270.         Status('Ringing...');
  4271.       { DoPersonalize will perform the ringing sound loop }
  4272.       //PlaySound(pChar('FMA_CallReceived'), 0, SND_ASYNC or SND_APPLICATION or SND_NODEFAULT);
  4273.     end;
  4274.   end;
  4275. end;
  4276.  
  4277. procedure TForm1.HandleCOPS(AMsg: String);
  4278. var
  4279.   sl: TstringList;
  4280. begin
  4281.   {
  4282.   AT+COPS?
  4283.   +COPS: 0,0,"M-TEL GSM BG"
  4284.   ATZCOPS=?
  4285.   +COPS: (2,"M-TEL GSM BG","BG M-TEL","28401")
  4286.   +COPS: (3,"BG GLOBUL","BG GLOBUL","28405")
  4287.   }
  4288.   Delete(AMsg,1,7);
  4289.   sl := TstringList.Create;
  4290.   try
  4291.     sl.CommaText := AMsg;
  4292.     if sl.Count < 3 then
  4293.       FSelOperator := 'Unknown'
  4294.     else
  4295.       FSelOperator := sl[2];
  4296.   finally
  4297.     sl.Free;
  4298.   end;
  4299. end;
  4300.  
  4301. procedure TForm1.HandleCKEV(AMsg: String);
  4302. var
  4303.   str: String;
  4304.   curKey: String;
  4305. begin
  4306.   if GetTickCount > FKeyMSec then begin
  4307.     FKeyActivity := '';
  4308.     FKeyState := False;
  4309.     Debug('Key Buffer: Cleanup due to inactivity');
  4310.   end;
  4311.   FKeyMSec := GetTickCount + Cardinal(FKeyInactivityTimeout);
  4312.  
  4313.   str := copy(AMsg, 8, length(AMsg));
  4314.  
  4315.   {
  4316.   try
  4317.     GetToken(str, 1);
  4318.   except
  4319.     FKeyState := not FKeyState;
  4320.     if FKeyState = True then str := str + ',1'
  4321.     else str := str + ',0';
  4322.     Debug('Dirty Fix: ' + str);
  4323.   end;
  4324.   }
  4325.  
  4326.   try
  4327.     if GetToken(str, 1) = '1' then begin
  4328.       curKey := GetToken(str, 0);
  4329.       FKeyActivity := FKeyActivity + curKey;
  4330.       Debug('Key Buffer: ' + FKeyActivity);
  4331.       ScriptEvent('OnKeyPress', [curKey, 1]);
  4332.     end
  4333.     else if GetToken(str, 1) = '0' then begin
  4334.       ScriptEvent('OnKeyPress', [curKey, 0]);
  4335.     end
  4336.     else begin
  4337.       Debug('Unknow key pressed');
  4338.     end;
  4339.   except
  4340.   end;
  4341. end;
  4342.  
  4343. procedure TForm1.HandleCIEV(AMsg: String);
  4344. var
  4345.    sl: TStringList;
  4346.    s: string;
  4347. begin
  4348.   {
  4349.   +CKEV: <ind>,<value>
  4350.  
  4351.   <ind> Description
  4352.   1 Battery charge level indicator
  4353.   2 Signal quality indicator
  4354.   3 Battery warning indicator
  4355.   4 Charger connected indicator
  4356.   5 Service availability indicator
  4357.   6 Sounder activity indicator
  4358.   7 Message received indicator
  4359.   8 Call-in-progress indicator
  4360.   9 Transmit activated by voice activity indicator
  4361.   10 Roaming indicator
  4362.   11 Short message memory storage indicator in the SMS
  4363.   12 Bluetooth proprietary call set up status indicator
  4364.  
  4365.   <value> Description (range)
  4366.   1 ôbattchgö battery charge level (0-5)
  4367.   2 ôsignalö signal quality (0-5)
  4368.   3 ôbatterywarningö batterywarning (0-1)
  4369.   4 ôchargerconnectedö chargerconnected (0-1)
  4370.   5 ôserviceö service availability (0-1) (Net contact status, 1 = Net contact)
  4371.   6 ôsounderö sounder activity (0-1) (Phone silent status, 1 = phone silent)
  4372.   7 ômessageö message received (0-1)
  4373.   8 ôcallö call in progress (0-1)
  4374.   9 ôvoxö transmit activated by voice activity (0-1) Not supported
  4375.   10 ôroamö roaming indicator (0-1) (Home net status, 0 = Home Net)
  4376.   11 ôsmsfullö a short message memory storage in the MT has become full (1), or memory locations are available (0); i.e. the range is (0-1)
  4377.   12 "callsetup" Bluetooth proprietary call set up status indicator. Not currently in call set up (0), incoming call process
  4378.      ongoing (1), outgoing call set up is ongoing (2), remote party being alerted in an outgoing call (3); i.e the range is (0-3)
  4379.   }
  4380.   try
  4381.     sl := TStringList.Create;
  4382.     try
  4383.       sl.DelimitedText := copy(AMsg, 8, length(AMsg));
  4384.       case StrToInt(sl[0]) of
  4385.         11: if sl[1] = '1' then begin
  4386.               s := 'Phone SMS storage is full. Please delete some messages.';
  4387.               CoolTrayIcon1.ShowBalloonHint(Application.Title,s,bitWarning,60);
  4388.               Debug(s);
  4389.             end;
  4390.       end;
  4391.     finally
  4392.       sl.Free;
  4393.     end;
  4394.   except
  4395.   end;
  4396. end;
  4397.  
  4398. procedure TForm1.HandleEBCA(AMsg: String);
  4399.  
  4400.  function MakeReadable(Value: double; Units: array of string; Divider: word = 1000): string; overload;
  4401.  var UnitIndex: integer;
  4402.  begin
  4403.   UnitIndex := 0;
  4404.  
  4405.   while (Value > Divider) and (UnitIndex < Length(Units)) do
  4406.   begin
  4407.    Inc(UnitIndex);
  4408.    Value := Value / Divider;
  4409.   end;
  4410.  
  4411.   result := FormatFloat('##0.##', Value) + ' ' + Units[UnitIndex];
  4412.  end;
  4413.  
  4414.  function MakeReadable(Value: string; Units: array of string; Divider: word = 1000): string; overload;
  4415.  begin
  4416.   result := MakeReadable(StrToFloatDef(Value, 0), Units, Divider);
  4417.  end;
  4418.  
  4419. var
  4420.    sl :TStringList;
  4421.    vbat :integer;
  4422.    consumption:Integer;
  4423. begin
  4424.    if not FUseEBCA or (frmInfoView = nil) then exit;
  4425.    try
  4426.      sl := TStringList.Create;
  4427.      try
  4428.        sl.DelimitedText := copy(AMsg, 8, length(AMsg));
  4429.        if sl.Count < 4 then exit;
  4430.  
  4431.        // Check for K700i! There should be a better way?? Like taking the product Id or name into account :)
  4432.        if sl.Count <> 14 then
  4433.        begin
  4434.        //battery voltage
  4435.        vbat := strtoint(sl.Strings[1]) * 10 +
  4436.           strtoint(sl.Strings[2]) * 10 +
  4437.           strtoint(sl.Strings[3]) * 10 +
  4438.           strtoint(sl.Strings[0]) * 10;
  4439.  
  4440.        frmInfoView.lbvbat.Caption := MakeReadable(vbat, ['mV', 'V', 'kV']);
  4441.  
  4442.        //battery type
  4443.        case strtoint(sl.Strings[4]) of
  4444.           0: frmInfoView.lbPower.Caption := 'NiMH Battery';
  4445.           1: frmInfoView.lbPower.Caption := 'Litium ion/Polymer Battery';
  4446.           2: frmInfoView.lbPower.Caption := 'Unknown Battery';
  4447.        end;
  4448.  
  4449.        //battery voltage from the charge
  4450.        frmInfoView.lbdcio.Caption := MakeReadable(strtoint(sl.Strings[5]) * 10, ['mV', 'V', 'kV']);
  4451.  
  4452.        //current charge
  4453.        if sl.Count = 27 then begin
  4454.           frmInfoView.lbicharge.Caption := MakeReadable(strtoint(sl.Strings[6])/10, ['mA', 'A']);
  4455.           frmInfoView.Chart1.Series[1].Add(Round(strtoint(sl.Strings[6])/10));
  4456.        end
  4457.        else begin
  4458.           frmInfoView.lbicharge.Caption := MakeReadable(sl.Strings[6], ['mA', 'A']);
  4459.           frmInfoView.Chart1.Series[1].Add(strtoint(sl.Strings[6]));
  4460.        end;
  4461.  
  4462.        //phone current consumption
  4463.        if sl.Count = 27 then begin
  4464.           frmInfoView.lbiphone.Caption := MakeReadable(strtoint(sl.Strings[7])/10, ['mA', 'A']);
  4465.           frmInfoView.Chart1.Series[2].Add(Round(strtoint(sl.Strings[7])/10));
  4466.        end
  4467.        else begin
  4468.           frmInfoView.lbiphone.Caption := MakeReadable(sl.Strings[7], ['mA', 'A']);
  4469.           frmInfoView.Chart1.Series[2].Add(strtoint(sl.Strings[7]));
  4470.        end;
  4471.  
  4472.        // scroll chart if it's full
  4473.        if frmInfoView.Chart1.Series[0].Count > frmInfoView.Chart1.MaxPointsPerPage then begin
  4474.           with frmInfoView.Chart1.BottomAxis do Scroll(1,False);
  4475.           inc(ChartShiftCnt);
  4476.        end;
  4477.  
  4478.        //phone and battery temperature
  4479.        if sl.Count = 24 then begin
  4480.           frmInfoView.lbtempbatt.Caption := inttostr(strtoint(sl.Strings[10])) + '░C';
  4481.           frmInfoView.lbtempphone.Caption := inttostr(strtoint(sl.Strings[11])) + '░C';
  4482.        end
  4483.        else begin
  4484.           frmInfoView.lbtempbatt.Caption := inttostr(strtoint(sl.Strings[12])) + '░C';
  4485.           frmInfoView.lbtempphone.Caption := inttostr(strtoint(sl.Strings[13])) + '░C';
  4486.        end;
  4487.        frmInfoView.Chart1.Series[0].Add(strtoint(sl.Strings[12]));
  4488.  
  4489.        try //ADD because not all support all EBCA's values  //this causes the error "List index out of bounds (16)"
  4490.           //number of charge cycles
  4491.           if sl.Count > 24 then begin
  4492.              frmInfoView.lbcyclescharge.Caption := sl.Strings[16]; // + ' times';
  4493.              //CalculateTimeLeft(StatusBar.Panels[1].Text,sl.Strings[16],pbPower.Position,pbPower.MaxValue);
  4494.           end;
  4495.        except
  4496.           frmInfoView.lbcyclescharge.Visible := False;
  4497.        end;
  4498.        end else // Special handling of K700i message
  4499.        begin
  4500.            //battery voltage
  4501.            vbat := strtoint(sl.Strings[0]); // mV
  4502.            frmInfoView.lbvbat.Caption := MakeReadable(vbat, ['mV', 'V', 'kV']);
  4503.  
  4504.            //battery type
  4505.            //this has to be rechecked!! I have a polymer and it is reporting 0 ???
  4506.            case strtoint(sl.Strings[6]) of
  4507.               0: frmInfoView.lbPower.Caption := 'Lithium polymer Battery';
  4508.               1: frmInfoView.lbPower.Caption := 'Litium ion Battery';
  4509.               2: frmInfoView.lbPower.Caption := 'NiMH Battery';
  4510.               else frmInfoView.lbPower.Caption := 'Unknown';
  4511.  
  4512.            end;
  4513.            //battery voltage from the charge
  4514.            frmInfoView.lbdcio.Caption := MakeReadable(strtoint(sl.Strings[1]), ['mV', 'V', 'kV']);
  4515.  
  4516.            //current charge
  4517.            frmInfoView.lbicharge.Caption := MakeReadable(strtoint(sl.Strings[2])/10.0, ['mA', 'A']);
  4518.            frmInfoView.Chart1.Series[1].Add(strtoint(sl.Strings[3]) div 10);
  4519.  
  4520.            consumption := abs(strtoint(sl.Strings[3]));
  4521.            begin
  4522.              //phone current consumption
  4523.              frmInfoView.lbiphone.Caption := MakeReadable(consumption/10.0, ['mA', 'A']);
  4524.              frmInfoView.Chart1.Series[2].Add(consumption DIV 10);
  4525.            end;
  4526.  
  4527.            // scroll chart if it's full
  4528.            if frmInfoView.Chart1.Series[0].Count > frmInfoView.Chart1.MaxPointsPerPage then begin
  4529.               with frmInfoView.Chart1.BottomAxis do Scroll(1,False);
  4530.               inc(ChartShiftCnt);
  4531.            end;
  4532.  
  4533.            //phone and battery temperature
  4534.            frmInfoView.lbtempbatt.Caption := inttostr(strtoint(sl.Strings[4])) + '░C';
  4535.            frmInfoView.lbtempphone.Caption := inttostr(strtoint(sl.Strings[5])) + '░C';
  4536.            frmInfoView.Chart1.Series[0].Add(strtoint(sl.Strings[4]));
  4537.  
  4538.            try
  4539.                  frmInfoView.lbcyclescharge.Caption := sl.Strings[11]; // + ' times';
  4540.                  //CalculateTimeLeft(StatusBar.Panels[1].Text,sl.Strings[16],pbPower.Position,pbPower.MaxValue);
  4541.            except
  4542.               frmInfoView.lbcyclescharge.Visible := False;
  4543.            end;
  4544.        end;
  4545.      finally
  4546.        sl.Free;
  4547.      end;
  4548.    except
  4549.    end;
  4550. end;
  4551.  
  4552. procedure TForm1.Timer1Timer(Sender: TObject);
  4553. begin
  4554.   if not Timer2.Enabled then exit;
  4555.   Timer1.Enabled := False;
  4556.   if Application.Terminated then
  4557.     exit;
  4558.   try
  4559.     if FConnected and FConnectingComplete and Assigned(FObex) and not FObex.Connected and not FObexConnecting and
  4560.       not frmCalling.IsCalling and not frmCalling.IsTalking and (ActiveThread = nil) and not FBusy then 
  4561.       try
  4562.         try
  4563.           //if frmInfoView.Visible then EBCAState(False);
  4564.           if Timer1.Tag = 1 then begin
  4565.             TxAndWait('AT+CSQ');
  4566.             Timer1.Tag := 0;
  4567.           end
  4568.           else begin
  4569.             TxAndWait('AT+CBC');
  4570.             Timer1.Tag := 1;
  4571.           end;
  4572.         finally
  4573.           if frmInfoView.Visible then begin
  4574.             frmInfoView.UpdateWelcomePage;
  4575.           end;
  4576.         end;
  4577.       except
  4578.       end;
  4579.   finally
  4580.     Timer1.Enabled := True;
  4581.   end;
  4582. end;
  4583.  
  4584. procedure TForm1.HandleStatus(AMsg: String);
  4585. var
  4586.   s,str: String;
  4587.   signal: Integer;
  4588.   function Percentage(Pos,Max: integer): string;
  4589.   begin
  4590.     Result := IntToStr(Round((100*Pos)/Max))+'%';
  4591.   end;
  4592. begin
  4593.   str := copy(AMsg, 7, length(AMsg));
  4594.  
  4595.   if pos('+CBC', AMsg) = 1 then begin
  4596.     signal := StrToInt(GetToken(str, 1));
  4597.     FOnACPower := GetToken(str, 0) = '1';
  4598.     if FOnACPower then begin
  4599.       SetPanelText(2, 'AC Power');
  4600.       FBatteryWarning := False;
  4601.     end
  4602.     else begin
  4603.       SetPanelText(2, 'Battery '+Percentage(signal,pbPower.MaxValue));
  4604.       FBatteryLow := signal < 2;
  4605.       if FBatteryLow and not FBatteryWarning and FConnectingComplete then begin
  4606.         FBatteryWarning := True;
  4607.         str := 'The phone battery is too low! Plug the phone into the charger now if you wish to use Fma...';
  4608.         Status(str);
  4609.         CoolTrayIcon1.ShowBalloonHint(Application.Title,str,bitWarning,60);
  4610.         //ShowBaloonInfo(str,60);
  4611.       end;
  4612.     end;
  4613.     pbPower.Position := signal;
  4614.     s := frmInfoView.lbcyclescharge.Caption;
  4615.     if (s <> '') and not (s[1] in ['0'..'9']) then s := '';
  4616.     CalculateTimeLeft(StatusBar.Panels[1].Text,s,pbPower.Position,pbPower.MaxValue);
  4617.  
  4618.     if signal < 1 then begin
  4619.       Debug('Battery is too low... Going to Offline mode...');
  4620.       ActionConnectionAbort.Execute;
  4621.       if FConnectingComplete then
  4622.         ActionConnectionDisconnect.Execute
  4623.       else
  4624.         raise Exception.Create('Disconnected due to low battery');
  4625.       Status('Disconnected due to low battery');
  4626.     end;
  4627.   end;
  4628.  
  4629.   if pos('+CSQ', AMsg) = 1 then begin
  4630.     signal := StrToInt(GetToken(str, 0));
  4631.     if signal = 99 then begin
  4632.       SetPanelText(3, 'Signal N/A');
  4633.       pbRSSI.Position := 0;
  4634.     end
  4635.     else begin
  4636.       signal := Round((signal / 31) * 100);
  4637.       SetPanelText(3, ' Signal '+Percentage(signal,pbRSSI.MaxValue)+' ');
  4638.       pbRSSI.Position := signal;
  4639.     end;
  4640.   end;
  4641. end;
  4642.  
  4643. procedure TForm1.HandleNewSMS(AMsg: String);
  4644. var
  4645.   str, memLocation: String;
  4646.   index: Integer;
  4647. begin
  4648.   { Should we monitor messages? }
  4649.   if not FMsgM then exit;
  4650.  
  4651.   { Yes, do it }
  4652.   str := copy(AMsg, 8, length(AMsg));
  4653.   memLocation := GetToken(str, 0);
  4654.   index := StrToInt(GetToken(str, 1));
  4655.  
  4656.   { Now download message }
  4657.   DownloadSMS(memLocation, index);
  4658.  
  4659.   { Clear the msgbox after receive, if needed...
  4660.     CNMI mode 3 just forwards message to Fma and do not
  4661.     keep it on phone, so we don't have to delete the
  4662.     message box (have to be tested), which leads to:
  4663.     849510 Active call interruption on incoming SMS }
  4664.   if not FUseCNMIMode3 then begin
  4665.     if not frmCalling.IsTalking and not frmCalling.IsCalling then // do not cancel active call here
  4666.       { Schedule execution... }
  4667.       FClearPhoneMessage := True;
  4668.       { TODO: handle else state? for now the message will stay on phone }
  4669.   end;
  4670. end;
  4671.  
  4672. procedure TForm1.ApplicationEvents1Minimize(Sender: TObject);
  4673. begin
  4674.   if frmInfoView.Visible then EBCAState(False,False);
  4675.   if FormStorage1.StoredValue['StartMinimized'] = False then begin
  4676.     FloatingRectangles(True, False);
  4677.     FormStorage1.StoredValue['StartMinimized'] := True;
  4678.   end;
  4679.   ShowRestore1.Action := ActionWindowRestore;
  4680. end;
  4681.  
  4682. procedure TForm1.ApplicationEvents1Restore(Sender: TObject);
  4683. begin
  4684.   FormStorage1.StoredValue['StartMinimized'] := False;
  4685.   ShowRestore1.Action := ActionWindowMinimize;
  4686.   if frmInfoView.Visible then begin
  4687.     { Make sure we will enable EBCA since we dont know its actual state during Minimized App state }
  4688.     EBCALastState := -1;
  4689.     EBCAState(True,False);
  4690.   end;  
  4691. end;
  4692.  
  4693. procedure TForm1.SetPanelText(id: Integer; str: String);
  4694. begin
  4695.   StatusBar.Panels[id].Text := str;
  4696.   StatusBar.Canvas.Font := StatusBar.Font;
  4697.   StatusBar.Panels[id].Width := Canvas.TextWidth(str) + 20;
  4698. end;
  4699.  
  4700. procedure TForm1.ActionAboutExecute(Sender: TObject);
  4701. begin
  4702.   frmAbout := TfrmAbout.Create(Self);
  4703.   try
  4704.     frmAbout.ShowModal;
  4705.   finally
  4706.     frmAbout.Free;
  4707.   end;
  4708. end;
  4709.  
  4710. procedure TForm1.ActionWindowRestoreExecute(Sender: TObject);
  4711. begin
  4712.   FloatingRectangles(False, False);
  4713.   Show;
  4714.   Application.Restore;
  4715.   Application.BringToFront;
  4716. end;
  4717.  
  4718. procedure TForm1.LoadOptions;
  4719. begin
  4720.   try
  4721.     FormStorage1.StoredValues.RestoreValues;
  4722.     FObex.MaxPacketSize := FormStorage1.StoredValue['MaxPacketSize'];
  4723.     FInactivityTimeout := FormStorage1.StoredValue['CommTimeout'];
  4724.     FScriptFile := FormStorage1.StoredValue['ScriptFile'];
  4725.     FUseScript := FormStorage1.StoredValue['UseScript'];
  4726.     FConnectionType := FormStorage1.StoredValue['ConnectionType'];
  4727.     FExplorerStartupMode := FormStorage1.StoredValue['ExplorerStartup'];
  4728.     FSMSDoWarning := FormStorage1.StoredValue['SMSDoWarning'];
  4729.     FSMSDoReset := FormStorage1.StoredValue['SMSDoReset'];
  4730.     FBTAddress := FormStorage1.StoredValue['BluetoothAddr'];
  4731.     FBtPort := FormStorage1.StoredValue['BluetoothPort'];
  4732.     ComPort.FlowControl.ControlRTS := TRTSFlowControl(FormStorage1.StoredValue['ComPortControlRTS']);
  4733.     ComPort.FlowControl.ControlDTR := TDTRFlowControl(FormStorage1.StoredValue['ComPortControlDTR']);
  4734.     FAlphaCall := FormStorage1.StoredValue['AlphaCall'];
  4735.     FAlphaDebug := FormStorage1.StoredValue['AlphaDebug'];
  4736.     FAlphaMessage := FormStorage1.StoredValue['AlphaMessage'];
  4737.     FAlphaCompose := FormStorage1.StoredValue['AlphaCompose'];
  4738.  
  4739.     FCallM := FormStorage1.StoredValue['Call Monitor'];
  4740.     FMsgM := FormStorage1.StoredValue['Message Monitor'];
  4741.  
  4742.     FStateMonitor := FormStorage1.StoredValue['State Monitor'];
  4743.     FShowDiagram := FormStorage1.StoredValue['Phone Diagram'];
  4744.     FShowTodayCaption := FormStorage1.StoredValue['Today Caption'];
  4745.  
  4746.     FMinimize := FormStorage1.StoredValue['Minimize'];
  4747.     FCheckOutbox := FormStorage1.StoredValue['Check Outbox'];
  4748.  
  4749.     FSyncConflict := FormStorage1.StoredValue['Sync Conflict'];
  4750.     FClockSync := FormStorage1.StoredValue['Clock Sync'];
  4751.     FDontProgress := FormStorage1.StoredValue['Dont Progress'];
  4752.     FProgressLongOnly := FormStorage1.StoredValue['Progress Long'];
  4753.     FProgressRestoredOnly := FormStorage1.StoredValue['Progress Restored'];
  4754.  
  4755.     FOutlookSyncConflict := FormStorage1.StoredValue['Outlook Sync Conflict'];
  4756.     FOutlookConfirmAdding := FormStorage1.StoredValue['Outlook Sync Confirm Adding'];
  4757.     FOutlookConfirmUpdating := FormStorage1.StoredValue['Outlook Sync Confirm Updating'];
  4758.     FOutlookConfirmDeleting := FormStorage1.StoredValue['Outlook Sync Confirm Deleting'];
  4759.     FOutlookNewAction := FormStorage1.StoredValue['Outlook New Action'];
  4760.     FOutlookNewContactsFolder := FormStorage1.StoredValue['Outlook New Contacts Folder'];
  4761.  
  4762. //  FConnectOnLaunch := FormStorage1.StoredValue['ConnectOnLaunch'];
  4763. //  FAutoReconnect := FormStorage1.StoredValue['AutoReconnect'];
  4764.     DoStrictUCScheck := FormStorage1.StoredValue['StrictUCS2'];
  4765.     ForceUCSusage := FormStorage1.StoredValue['ForceUCS2'];
  4766.     with FStartupOptions do begin
  4767.       NoObex := FormStorage1.StoredValue['NoObex'];
  4768.       NoIRMC := FormStorage1.StoredValue['NoIRMC'];
  4769.       NoGroups := FormStorage1.StoredValue['NoGroups'];
  4770.       NoFolders := FormStorage1.StoredValue['NoFolders'];
  4771.       NoProfiles := FormStorage1.StoredValue['NoProfiles'];
  4772.       NoCalls := FormStorage1.StoredValue['NoCalls'];
  4773.       NoBookmarks := FormStorage1.StoredValue['NoBookmarks'];
  4774.     end;
  4775.     with FProximityOptions do begin
  4776.       AwayLock := FormStorage1.StoredValue['AwayLock'];
  4777.       NearUnlock := FormStorage1.StoredValue['NearUnlock'];
  4778.       AwayMusicMode := FormStorage1.StoredValue['AwayMusicMode'];
  4779.       NearMusicMode := FormStorage1.StoredValue['NearMusicMode'];
  4780.       RunSS := FormStorage1.StoredValue['RunSS'];
  4781.     end;
  4782.     with FTextMessageOptions do begin
  4783.       NoPopup := FormStorage1.StoredValue['MsgNoPopup'];
  4784.       NoBaloon := FormStorage1.StoredValue['MsgNoBaloon'];
  4785.       MoveToArchive := FormStorage1.StoredValue['MsgAutoArchive'];
  4786.       FullWarning := FormStorage1.StoredValue['MsgFullWarning'];
  4787.     end;
  4788.     FAutoProfile := FormStorage1.StoredValue['AutoProfile'] <> '';
  4789.   except
  4790.   end;
  4791. end;
  4792.  
  4793. procedure TForm1.ActionToolsOptionsExecute(Sender: TObject);
  4794. begin
  4795.   frmOptions := TfrmOptions.Create(Self);
  4796.   With frmOptions do
  4797.   try
  4798.     // Connection
  4799.     connectionType := FConnectionType;
  4800.     edBTAddress.Text := FBTAddress;
  4801.     edBTPortSpin.Position := StrToInt(FBtPort);
  4802.     sePort.Text := ComPort.Port;
  4803.     cbBaudrate.ItemIndex := Integer(ComPort.BaudRate);
  4804.     cbRTSFlow.ItemIndex := Integer(ComPort.FlowControl.ControlRTS);
  4805.     cbDTRFlow.ItemIndex := Integer(ComPort.FlowControl.ControlDTR);
  4806.  
  4807.     // Communication
  4808.     sePollingSpin.Position := Round(Timer1.Interval / 1000);
  4809.     seCommTimeoutSpin.Position := Round(FInactivityTimeout / 1000);
  4810.     chkStateMonitor.Checked := FStateMonitor;
  4811.     cbDiagram.Checked := FShowDiagram;
  4812.     cbAutoProfile.Checked := FAutoProfile;
  4813.  
  4814.     // OBEX
  4815.     seMaxPacketSizeSpin.Position := FObex.MaxPacketSize;
  4816.  
  4817.     // Scripts
  4818.     edScriptPath.Text := FScriptFile;
  4819.     cbUseScripts.Checked := FUseScript;
  4820.  
  4821.     //Alpha
  4822.     seComposeSpin.Position := FAlphaCompose;
  4823.     seCallSpin.Position := FAlphaCall;
  4824.     seDebugSpin.Position := FAlphaDebug;
  4825.     seMessageSpin.Position := FAlphaMessage;
  4826.  
  4827.     //Monitor
  4828.     chkCallM.Checked := FCallM;
  4829.     chkMsgM.Checked := FMsgM;
  4830.     chkMsgMClick(nil);
  4831.     with FTextMessageOptions do begin
  4832.       cbNoMsgPopup.Checked := NoPopup;
  4833.       cbNoMsgBaloon.Checked := NoBaloon;
  4834.       cbMsgToArchive.Checked := MoveToArchive;
  4835.       cbMsgFullWarning.Checked := FullWarning;
  4836.     end;
  4837.  
  4838.     chkMinButton.Checked := FMinimize;
  4839.     cbCheckOutbox.Checked := FCheckOutbox;
  4840.  
  4841.     //Synchronize
  4842.     rbSync.ItemIndex := FSyncConflict;
  4843.     rbPhoneClockSync.ItemIndex := FClockSync;
  4844.     cbAutoInbox.Checked := FormStorage1.StoredValue['AutoInbox'] = True;
  4845.     cbAutoSync.Checked := FormStorage1.StoredValue['AutoSync'] = True;
  4846.     cbAutoOutlookSync.Checked := FormStorage1.StoredValue['AutoSyncOutlook'] = True;
  4847.     cbAutoBookmarks.Checked := FormStorage1.StoredValue['AutoBookmarks'] = True;
  4848.     edBookmarkDir.Text := FBookmarkRootFolder;
  4849.  
  4850.     //Outlook Sync
  4851.     rbOutlookSync.ItemIndex := FOutlookSyncConflict;
  4852.     cbConfirmAdding.Checked := FOutlookConfirmAdding;
  4853.     cbConfirmUpdating.Checked := FOutlookConfirmUpdating;
  4854.     cbConfirmDeleting.Checked := FOutlookConfirmDeleting;
  4855.     OutlookCategories := FOutlookCategories;
  4856.     cbOutlookAllCategories.Checked := FOutlookCategories = '';
  4857.     rbOutlookNewAction.ItemIndex := FOutlookNewAction;
  4858.     SelectedOutlookFolders := FSelectedOutlookFolders;
  4859.     OutlookNewContactsFolder := FOutlookNewContactsFolder;
  4860.  
  4861.     //Regional settings
  4862.     cbForceUCS2.Checked := ForceUCSusage;
  4863.     cbStrictUCScheck.Checked := DoStrictUCScheck;
  4864.  
  4865.     // Interface
  4866.     cbProgressLongOnly.Checked := FProgressLongOnly;
  4867.     cbProgressRestoredOnly.Checked := FProgressRestoredOnly;
  4868.     cbDontProgress.Checked := FDontProgress;
  4869.     cbDontProgressClick(nil);
  4870.  
  4871.     // Startup Options
  4872.     with FStartupOptions do begin
  4873.       cbNoIRMC.Checked := NoIRMC;
  4874.       cbNoGroups.Checked := NoGroups;
  4875.       cbNoFolders.Checked := NoFolders;
  4876.       cbNoProfiles.Checked := NoProfiles;
  4877.       cbNoProfilesClick(nil);
  4878.       cbNoCalls.Checked := NoCalls;
  4879.       cbNoBookmarks.Checked := NoBookmarks;
  4880.       cbNoObex.Checked := NoObex;
  4881.       cbNoObexClick(nil);
  4882.     end;
  4883.  
  4884.     // Appearance
  4885.     rgExplorer.ItemIndex := FExplorerStartupMode;
  4886.     cbSMSWarning.Checked := FSMSDoWarning;
  4887.     cbSMSReset.Checked := FSMSDoReset;
  4888.     udSMSCnt.Position := FSMSWarning;
  4889.     udSMSCntRst.Position := FSMSCounterResetDay;
  4890.  
  4891.     // Proximity settings
  4892.     with FProximityOptions do begin
  4893.       cbProximityLock.Checked := AwayLock;
  4894.       rgProximityAway.ItemIndex := AwayMusicMode;
  4895.       cbProximityUnlock.Checked := NearUnlock;
  4896.       rgProximityNear.ItemIndex := NearMusicMode;
  4897.       cbRunSS.Checked := RunSS;
  4898.     end;
  4899.  
  4900.     if ShowModal = mrOK then begin
  4901.       // Appearance
  4902.       FSMSDoWarning := cbSMSWarning.Checked;
  4903.       FormStorage1.StoredValue['SMSDoWarning'] := FSMSDoWarning;
  4904.       FSMSDoReset := cbSMSReset.Checked;
  4905.       FormStorage1.StoredValue['SMSDoReset'] := FSMSDoReset;
  4906.       FExplorerStartupMode := rgExplorer.ItemIndex;
  4907.       FormStorage1.StoredValue['ExplorerStartup'] := FExplorerStartupMode;
  4908.       FSMSWarning := udSMSCnt.Position;
  4909.       FSMSCounterResetDay := udSMSCntRst.Position;
  4910.  
  4911.       // Proximity settings
  4912.       with FProximityOptions do begin
  4913.         AwayLock := cbProximityLock.Checked;
  4914.         AwayMusicMode := rgProximityAway.ItemIndex;
  4915.         NearUnlock := cbProximityUnlock.Checked;
  4916.         NearMusicMode := rgProximityNear.ItemIndex;
  4917.         RunSS := cbRunSS.Checked;
  4918.         FormStorage1.StoredValue['AwayLock'] := AwayLock;
  4919.         FormStorage1.StoredValue['AwayMusicMode'] := AwayMusicMode;
  4920.         FormStorage1.StoredValue['NearUnlock'] := NearUnlock;
  4921.         FormStorage1.StoredValue['NearMusicMode'] := NearMusicMode;
  4922.         FormStorage1.StoredValue['RunSS'] := RunSS;
  4923.       end;
  4924.  
  4925.       // Startup Options
  4926.       with FStartupOptions do begin
  4927.         NoObex := cbNoObex.Checked;
  4928.         NoIRMC := cbNoIRMC.Checked;
  4929.         NoGroups := cbNoGroups.Checked;
  4930.         NoFolders := cbNoFolders.Checked;
  4931.         NoProfiles := cbNoProfiles.Checked;
  4932.         NoCalls := cbNoCalls.Checked;
  4933.         NoBookmarks := cbNoBookmarks.Checked;
  4934.         FormStorage1.StoredValue['NoObex'] := NoObex;
  4935.         FormStorage1.StoredValue['NoIRMC'] := NoIRMC;
  4936.         FormStorage1.StoredValue['NoGroups'] := NoGroups;
  4937.         FormStorage1.StoredValue['NoFolders'] := NoFolders;
  4938.         FormStorage1.StoredValue['NoProfiles'] := NoProfiles;
  4939.         FormStorage1.StoredValue['NoCalls'] := NoCalls;
  4940.         FormStorage1.StoredValue['NoBookmarks'] := NoBookmarks;
  4941.       end;
  4942.       FAutoProfile := cbAutoProfile.Checked;
  4943.       if FAutoProfile then FormStorage1.StoredValue['AutoProfile'] := cbProfile.Text
  4944.         else FormStorage1.StoredValue['AutoProfile'] := '';
  4945.  
  4946.       // Activate/Save the changes
  4947.       try
  4948.         if ComPort.BaudRate <> StrToBaudRate(cbBaudrate.Text) then
  4949.           ComPort.BaudRate := StrToBaudRate(cbBaudrate.Text);
  4950.       except
  4951.         Status('Reconnection needed (Baudrate changed)');
  4952.       end;
  4953.  
  4954.       try
  4955.         if ComPort.Port <> sePort.Text then
  4956.           ComPort.Port := sePort.Text;
  4957.       except
  4958.         Status('Serial port/device change Failed');
  4959.       end;
  4960.  
  4961.       try
  4962.         if Integer(ComPort.FlowControl.ControlRTS) <> cbRTSFlow.ItemIndex then
  4963.         begin
  4964.           ComPort.FlowControl.ControlRTS := TRTSFlowControl(cbRTSFlow.ItemIndex);
  4965.           FormStorage1.StoredValue['ComPortControlRTS'] := Integer(ComPort.FlowControl.ControlRTS);
  4966.         end;
  4967.  
  4968.         if Integer(ComPort.FlowControl.ControlDTR) <> cbDTRFlow.ItemIndex then
  4969.         begin
  4970.           ComPort.FlowControl.ControlDTR := TDTRFlowControl(cbDTRFlow.ItemIndex);
  4971.           FormStorage1.StoredValue['ComPortControlDTR'] := Integer(ComPort.FlowControl.ControlDTR);
  4972.         end;
  4973.       except
  4974.         Status('Flow Control change failed');
  4975.       end;
  4976.  
  4977.       if FConnectionType <> connectionType then begin
  4978.         ActionConnectionDisconnect.Execute;
  4979.         FConnectionType := connectionType;
  4980.         FormStorage1.StoredValue['ConnectionType'] := FConnectionType;
  4981.       end;
  4982.  
  4983.       FDontProgress := cbDontProgress.Checked;
  4984.       FormStorage1.StoredValue['Dont Progress'] := FDontProgress;
  4985.  
  4986.       FProgressLongOnly := cbProgressLongOnly.Checked;
  4987.       FProgressRestoredOnly := cbProgressRestoredOnly.Checked;
  4988.       FormStorage1.StoredValue['Progress Long'] := FProgressLongOnly;
  4989.       FormStorage1.StoredValue['Progress Restored'] := FProgressRestoredOnly;
  4990.  
  4991.       FBTAddress := edBTAddress.Text;
  4992.       FormStorage1.StoredValue['BluetoothAddr'] := FBTAddress;
  4993.  
  4994.       FBtPort := IntToStr(edBTPortSpin.Position);
  4995.       FormStorage1.StoredValue['BluetoothPort'] := FBtPort;
  4996.  
  4997.       Timer1.Interval := sePollingSpin.Position * 1000;
  4998.  
  4999.       FObex.MaxPacketSize := seMaxPacketSizeSpin.Position;
  5000.       FormStorage1.StoredValue['MaxPacketSize'] := FObex.MaxPacketSize;
  5001.  
  5002.       FInactivityTimeout := seCommTimeoutSpin.Position * 1000;
  5003.       FormStorage1.StoredValue['CommTimeout'] := FInactivityTimeout;
  5004.  
  5005.       FShowDiagram := cbDiagram.Checked;
  5006.       FormStorage1.StoredValue['Phone Diagram'] := FShowDiagram;
  5007.       FStateMonitor := chkStateMonitor.Checked;
  5008.       FormStorage1.StoredValue['State Monitor'] := FStateMonitor;
  5009.       if not FStateMonitor or frmInfoView.Visible then EBCAState(FStateMonitor);
  5010.  
  5011.       //alpha
  5012.       FAlphaCall := seCallSpin.Position;
  5013.       FormStorage1.StoredValue['AlphaCall'] := FAlphaCall;
  5014.       FAlphaDebug := seDebugSpin.Position;
  5015.       FormStorage1.StoredValue['AlphaDebug'] := FAlphaDebug;
  5016.       FAlphaMessage := seMessageSpin.Position;
  5017.       FormStorage1.StoredValue['AlphaMessage'] := FAlphaMessage;
  5018.       FAlphaCompose := seComposeSpin.Position;
  5019.       FormStorage1.StoredValue['AlphaCompose'] := FAlphaCompose;
  5020.       //make changes on form
  5021.       if frmDebug <> nil then
  5022.         frmDebug.AlphaBlendValue := FAlphaDebug;
  5023.       //frmCalling.AlphaBlendValue := FAlphaCall;
  5024.       //NewMsgForm.AlphaBlendValue := FAlphaCompose;
  5025.       //Monitor
  5026.       FCallM := chkCallM.Checked;
  5027.       FormStorage1.StoredValue['Call Monitor'] := FCallM;
  5028.       FMsgM := chkMsgM.Checked;
  5029.       FormStorage1.StoredValue['Message Monitor'] := FMsgM;
  5030.  
  5031.       FMinimize := chkMinButton.Checked;
  5032.       FormStorage1.StoredValue['Minimize'] := FMinimize;
  5033.       FCheckOutbox := cbCheckOutbox.Checked;
  5034.       FormStorage1.StoredValue['Check Outbox'] := FCheckOutbox;
  5035.  
  5036.       with FTextMessageOptions do begin
  5037.         NoPopup := cbNoMsgPopup.Checked;
  5038.         NoBaloon := cbNoMsgBaloon.Checked;
  5039.         MoveToArchive := cbMsgToArchive.Checked;
  5040.         FullWarning := cbMsgFullWarning.Checked;
  5041.         FormStorage1.StoredValue['MsgNoPopup'] := NoPopup;
  5042.         FormStorage1.StoredValue['MsgNoBaloon'] := NoBaloon;
  5043.         FormStorage1.StoredValue['MsgAutoArchive'] := MoveToArchive;
  5044.         FormStorage1.StoredValue['MsgFullWarning'] := FullWarning;
  5045.       end;
  5046.  
  5047.       //Synchronize
  5048.       FSyncConflict := rbSync.ItemIndex;
  5049.       FormStorage1.StoredValue['Sync Conflict'] := FSyncConflict;
  5050.       FClockSync := rbPhoneClockSync.ItemIndex;
  5051.       FormStorage1.StoredValue['Clock Sync'] := FClockSync;
  5052.       FormStorage1.StoredValue['AutoInbox'] := cbAutoInbox.Checked;
  5053.       FormStorage1.StoredValue['AutoSync'] := cbAutoSync.Checked;
  5054.       FormStorage1.StoredValue['AutoSyncOutlook'] := cbAutoOutlookSync.Checked;
  5055.       FormStorage1.StoredValue['AutoBookmarks'] := cbAutoBookmarks.Checked;
  5056.       FBookmarkRootFolder := edBookmarkDir.Text;
  5057.  
  5058.       //Outlook Synchronize
  5059.       FOutlookSyncConflict := rbOutlookSync.ItemIndex;
  5060.       FormStorage1.StoredValue['Outlook Sync Conflict'] := FOutlookSyncConflict;
  5061.       FOutlookConfirmAdding := cbConfirmAdding.Checked;
  5062.       FormStorage1.StoredValue['Outlook Sync Confirm Adding'] := FOutlookConfirmAdding;
  5063.       FOutlookConfirmUpdating := cbConfirmUpdating.Checked;
  5064.       FormStorage1.StoredValue['Outlook Sync Confirm Updating'] := FOutlookConfirmUpdating;
  5065.       FOutlookConfirmDeleting := cbConfirmDeleting.Checked;
  5066.       FormStorage1.StoredValue['Outlook Sync Confirm Deleting'] := FOutlookConfirmDeleting;
  5067.       if cbOutlookAllCategories.Checked then
  5068.         FOutlookCategories := ''
  5069.       else
  5070.         FOutlookCategories := OutlookCategories;
  5071.       FSelectedOutlookFolders := SelectedOutlookFolders;
  5072.       FOutlookNewAction := rbOutlookNewAction.ItemIndex;
  5073.       FormStorage1.StoredValue['Outlook New Action'] := FOutlookNewAction;
  5074.       FOutlookNewContactsFolder := OutlookNewContactsFolder;
  5075.       FormStorage1.StoredValue['Outlook New Contacts Folder'] := FOutlookNewContactsFolder;
  5076.  
  5077.       //Regional
  5078.       DoStrictUCScheck := cbStrictUCScheck.Checked;
  5079.       FormStorage1.StoredValue['StrictUCS2'] := DoStrictUCScheck;
  5080.       ForceUCSusage := cbForceUCS2.Checked;
  5081.       FormStorage1.StoredValue['ForceUCS2'] := ForceUCSusage;
  5082.  
  5083.       // Update view
  5084.       ExplorerChange(nil, Explorer.Selected);
  5085.  
  5086.       // Script
  5087.       FUseScript := cbUseScripts.Checked;
  5088.       FormStorage1.StoredValue['UseScript'] := FUseScript;
  5089.       if FScriptFile <> edScriptPath.Text then begin
  5090.         { First save the old script if modified }
  5091.         ApplyEditorChanges;
  5092.         { Then load new one }
  5093.         FScriptInitialized := False;
  5094.         FScriptFile := edScriptPath.Text;
  5095.         FormStorage1.StoredValue['ScriptFile'] := FScriptFile;
  5096.         ScriptInitialize;
  5097.       end;
  5098.     end;
  5099.   finally
  5100.     frmOptions.Free;
  5101.   end;
  5102. end;
  5103.  
  5104. procedure TForm1.ActionConnectionMonitorExecute(Sender: TObject);
  5105. begin
  5106. //  FUserConnect := ActionConnectionMonitor.Checked;
  5107. end;
  5108.  
  5109. procedure TForm1.ActionConnectionAutoConnectExecute(Sender: TObject);
  5110. begin
  5111. //  FConnectOnLaunch := ActionConnectionAutoConnect.Checked;
  5112. end;
  5113.  
  5114. procedure TForm1.SaveData;
  5115. var
  5116.   Fullpath,ID: string;
  5117.   i: integer;
  5118. begin
  5119.   { Should we save database? }
  5120.   if not FDatabaseLoaded then exit;
  5121.   { Yes, get last loaded database profile name }
  5122.   ID := PhoneIdentity;
  5123.   { Database dir path }
  5124.   Fullpath := ExePath;
  5125.   if ID <> '' then begin
  5126.     Fullpath := ExePath+'data\'+ID+'\dat\';
  5127.     { Create profile dir if needed }
  5128.     ForceDirectories(Fullpath);
  5129.   end;
  5130.   { Save phone database files into phone profile dir }
  5131.   if not IsAutoConnect then
  5132.     Debug('Database: Saving to '+Fullpath);
  5133.   with TIniFile.Create(Fullpath + 'Phone.dat') do
  5134.   try
  5135.     WriteString('Global','PhoneName',FSelPhone);
  5136.     WriteBool('SMS','Reset',FSMSCounterReseted);
  5137.     WriteInteger('SMS','Reset Day',FSMSCounterResetDay);
  5138.     WriteInteger('SMS','Count',FSMSCounter); 
  5139.     WriteInteger('SMS','Warning',FSMSWarning); 
  5140.     WriteString('Outlook','Categories',FOutlookCategories);
  5141.     WriteString('Outlook','ContactsFolder',FSelectedOutlookFolders);
  5142.     WriteString('Outlook','NewContactsFolder',FOutlookNewContactsFolder);
  5143.     WriteString('Bookmarks','Root',FBookmarkRootFolder);
  5144.     EraseSection('Favorites SMS');
  5145.     for i := 0 to FFavoriteRecipients.Count-1 do
  5146.       WriteString('Favorites SMS',IntToStr(i+1),FFavoriteRecipients[i]);
  5147.     EraseSection('Favorites Call');
  5148.     for i := 0 to FFavoriteCalls.Count-1 do
  5149.       WriteString('Favorites Call',IntToStr(i+1),FFavoriteCalls[i]);
  5150.   finally
  5151.     Free;
  5152.   end;
  5153.   TStrings(FNodeMsgInbox.Data).SaveToFile(Fullpath + 'SMSInbox.dat');
  5154.   TStrings(FNodeMsgOutbox.Data).SaveToFile(Fullpath + 'SMSOutbox.dat');
  5155.   TStrings(FNodeMsgSent.Data).SaveToFile(Fullpath + 'SMSSent.dat');
  5156.   TStrings(FNodeMsgArchive.Data).SaveToFile(Fullpath + 'SMSArchive.dat');
  5157.   TStrings(FNodeMsgDrafts.Data).SaveToFile(Fullpath + 'SMSDrafts.dat');
  5158.   TStrings(FNodeContactsME.Data).SaveToFile(Fullpath + 'Contacts.ME.dat');
  5159.   TStrings(FNodeContactsSM.Data).SaveToFile(Fullpath + 'Contacts.SM.dat');
  5160.   TStrings(FNodeBookmarks.Data).SaveToFile(Fullpath + 'Bookmarks.dat');
  5161.   frmSyncPhonebook.SaveContacts(Fullpath + 'Contacts.SYNC.dat');
  5162.   { Delete old common files, if any -- upgradeing from single database }
  5163.   if (ID <> '') and FileExists(ExePath + 'SMSInbox.dat') then
  5164.   try
  5165.     DeleteFile(ExePath + 'SMSInbox.dat');
  5166.     DeleteFile(ExePath + 'SMSOutbox.dat');
  5167.     DeleteFile(ExePath + 'SMSSent.dat');
  5168.     DeleteFile(ExePath + 'SMSArchive.dat');
  5169.     DeleteFile(ExePath + 'SMSDrafts.dat');
  5170.     DeleteFile(ExePath + 'Contacts.ME.dat');
  5171.     DeleteFile(ExePath + 'Contacts.SM.dat');
  5172.     DeleteFile(ExePath + 'Contacts.SYNC.dat');
  5173.     DeleteFile(ExePath + 'Contacts.SYNCMAX.dat');
  5174.     DeleteFile(ExePath + 'Bookmarks.dat');
  5175.     DeleteFile(ExePath + 'Phone.dat');
  5176.   except  
  5177.   end;
  5178. end;
  5179.  
  5180. procedure TForm1.ScriptControlError(Sender: TObject;
  5181.   Error: TawScriptError);
  5182. var
  5183.   s: string;
  5184. begin
  5185.   FScriptErrorOccur := True;
  5186.   s := Error.Description;
  5187.   if Trim(s) <> '' then s := '"'+s+'"';
  5188.   Debug(Format('Script: Error at line %d, col %d %s',[Error.Line,Error.Column,s]));
  5189. end;
  5190.  
  5191. procedure TForm1.ActionToolsEditScriptExecute(Sender: TObject);
  5192. begin
  5193.   Explorer.Selected := FNodeScripts;
  5194. end;
  5195.  
  5196. procedure TForm1.EnableKeyMonitor(TxDelay: boolean);
  5197. begin
  5198.   Debug('Enable Keypad Event Reporting');
  5199.   try
  5200.     if TxDelay then ScheduleTxAndWait('AT+CMER=3,2')
  5201.       else TxAndWait('AT+CMER=3,2'); // 2 = set keypad monitoring
  5202.     FKeyMonitoring := True;
  5203.   except;
  5204.   end;
  5205. end;
  5206.  
  5207. procedure TForm1.MinimizeApp;
  5208. begin
  5209.   ActionWindowMinimize.Execute;
  5210. end;
  5211.  
  5212. procedure TForm1.ActionConnectionAbortExecute(Sender: TObject);
  5213. begin
  5214.   DoAbort;
  5215. end;
  5216.  
  5217. procedure TForm1.VoiceCall(number: String);
  5218. begin
  5219.   if FHaveVoiceDialCommand_Dial then
  5220.     TxAndWait('AT*EVD="' + number + '"')
  5221.   else
  5222.     TxAndWait('ATDT' + number + ';');
  5223. end;
  5224.  
  5225. procedure TForm1.VoiceAnswer;
  5226. begin
  5227.   if FHaveVoiceDialCommand_Answer then
  5228.     TxAndWait('AT*EVA')
  5229.   else
  5230.     TxAndWait('ATA');
  5231. end;
  5232.  
  5233. procedure TForm1.VoiceHangUp(SilentMode: boolean);
  5234. var
  5235.   IsLocked: boolean;
  5236. begin
  5237.   { TODO: Use SilentMode to cancel a call without Busy sound to the caller WITHOUT using keypress }
  5238.   if SilentMode and IsT610Clone then begin
  5239.     { First unlock keyboard if needed }
  5240.     TxAndWait('AT+CLCK="CS",2');
  5241.     IsLocked := FKeybLocked;
  5242.     if IsLocked then
  5243.       ActionToolsKeybLock.Execute;
  5244.     { Cancel call silently, i.e. Remove ringing }
  5245.     try
  5246.       TxAndWait('AT+CKPD="c"');
  5247.     except
  5248.     end;
  5249.     { Lock keyboard again if needed }
  5250.     if IsLocked then
  5251.       ActionToolsKeybLock.Execute;
  5252.   end
  5253.   else
  5254.     if FHaveVoiceDialCommand_Hangup then
  5255.       TxAndWait('AT*EVH')
  5256.     else
  5257.       TxAndWait('ATH');
  5258.   if (frmCalling <> nil) and frmCalling.Visible then begin
  5259.     if not SilentMode then
  5260.       frmCalling.IsCalling := False;
  5261.     frmCalling.IsTalking := False;
  5262.     //frmCalling.Close;
  5263.   end;
  5264. end;
  5265.  
  5266. procedure TForm1.ActionToolsPostNoteExecute(Sender: TObject);
  5267. var
  5268.   sl: TStrings;
  5269.   stream: TStream;
  5270.   s: WideString;
  5271. begin
  5272.   with frmNote do begin
  5273.     if ShowModal = mrOK then begin
  5274.       s := Memo.Text;
  5275.       //s := StringReplace(s,#13#10,' ',[rfReplaceAll]);
  5276.       if s <> '' then begin
  5277.         sl := TStringList.Create;
  5278.         try
  5279.           sl.Add('BEGIN:VNOTE');
  5280.           sl.Add('VERSION:1.1');
  5281.           if FUseUTF8 then
  5282.             sl.Add('BODY;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:' + Str2QP(UTF8Encode(s)))
  5283.           else begin
  5284.             // ?? if FDoCharConvertion then s := ConvertCharSet(s,True);
  5285.             sl.Add('BODY;ENCODING=QUOTED-PRINTABLE:' + Str2QP(s));
  5286.           end;
  5287.           sl.Add('CLASS:'+frmNote.ComboBox1.Text);
  5288.           sl.Add('END:VNOTE');
  5289.  
  5290.           stream := TMemoryStream.Create;
  5291.           try
  5292.             sl.SaveToStream(stream);
  5293.  
  5294.             RequestConnection;
  5295.             FObex.PutObject('fma.vnt', stream, true);
  5296.           finally
  5297.             stream.Free;
  5298.             FlushOK;
  5299.           end;
  5300.         finally
  5301.           sl.Free;
  5302.         end;  
  5303.       end
  5304.       else begin
  5305.         Status('Nothing to post');
  5306.       end;
  5307.     end;
  5308.   end;
  5309. end;
  5310.  
  5311. function TForm1.LoadScript: boolean;
  5312. var
  5313.   FmaFunc,ext: String;
  5314. begin
  5315.   Result := True;
  5316.   if FScriptFile <> '' then begin
  5317.     if FileExists(FScriptFile) then begin
  5318.       ext := ExtractFileExt(FScriptFile);
  5319.       try
  5320.         frmEditor.Script.Lines.LoadFromFile(FScriptFile);
  5321.         ScriptControl.Code.BeginUpdate;
  5322.         try
  5323.           { load script from file }
  5324.           ScriptControl.Code.Clear;
  5325.           ScriptControl.Language := Copy(ext, 2, length(ext)-1);
  5326.           ScriptControl.Code.Assign(frmEditor.Script.Lines);
  5327.           { if Fma internal function does not exists, append it to script now
  5328.  
  5329.           Sub fname(command)
  5330.                   Execute(command)
  5331.           End Sub
  5332.           }
  5333.           FmaFunc := 'Sub '+__fma_objcall+'(command)';
  5334.           if ScriptControl.Code.IndexOf(FmaFunc) = -1 then begin
  5335.             Debug('Script: Adding FMA enchancements');
  5336.             ScriptControl.Code.Add('');
  5337.             ScriptControl.Code.Add(''' FMA enchancements - DO NOT REMOVE/ALTER THIS FUNCTION!!!');
  5338.             ScriptControl.Code.Add(FmaFunc);
  5339.             ScriptControl.Code.Add('  Execute(command)');
  5340.             ScriptControl.Code.Add('End Sub');
  5341.           end;
  5342.           { Thomas Wittek wrote (from scripts framework):
  5343.  
  5344.           Sub fname(command, arguments)
  5345.               If IsArray(arguments) And UBound(arguments) > -1 Then
  5346.                   ' Generate argument list
  5347.                   args = " "
  5348.                   For Each param In arguments
  5349.                           args = args & """" & param & """" & ", "
  5350.                   Next
  5351.                   ' Cut tailing ","
  5352.                   If Right(args, 2) = ", " Then args = Left(args, Len(args) -2)
  5353.               Else
  5354.                   args = ""
  5355.               End If
  5356.  
  5357.               Execute(command & args)
  5358.           End Sub
  5359.           }
  5360.           FmaFunc := 'Sub '+__fma_objcall+'Ex(command, arguments)';
  5361.           if ScriptControl.Code.IndexOf(FmaFunc) = -1 then begin
  5362.             Debug('Script: Adding FMA advanced enchancements');
  5363.             ScriptControl.Code.Add('');
  5364.             ScriptControl.Code.Add(''' FMA enchancements - DO NOT REMOVE/ALTER THIS FUNCTION!!!');
  5365.             ScriptControl.Code.Add(FmaFunc);
  5366.             ScriptControl.Code.Add('  Dim args, param');
  5367.             ScriptControl.Code.Add('  If IsArray(arguments) And UBound(arguments) > -1 Then');
  5368.             ScriptControl.Code.Add('      '' Generate argument list');
  5369.             ScriptControl.Code.Add('      args = " "');
  5370.             ScriptControl.Code.Add('      For Each param In arguments');
  5371.             ScriptControl.Code.Add('              args = args & """" & param & """" & ", "');
  5372.             ScriptControl.Code.Add('      Next');
  5373.             ScriptControl.Code.Add('      '' Cut tailing ","');
  5374.             ScriptControl.Code.Add('      If Right(args, 2) = ", " Then args = Left(args, Len(args) -2)');
  5375.             ScriptControl.Code.Add('  Else');
  5376.             ScriptControl.Code.Add('      args = ""');
  5377.             ScriptControl.Code.Add('  End If');
  5378.             ScriptControl.Code.Add('  Execute(command & args)');
  5379.             ScriptControl.Code.Add('End Sub');
  5380.           end;
  5381.         finally
  5382.           ScriptControl.Code.EndUpdate;
  5383.         end;
  5384.         Debug('Script: Loaded OK');
  5385.       except
  5386.         on e: Exception do begin
  5387.           Debug('Script: Load failed: '+e.Message);
  5388.           Result := False;
  5389.         end;
  5390.       end;
  5391.     end
  5392.     else
  5393.       Debug('Script: File "'+FScriptFile+'" not found');
  5394.   end;  
  5395. end;
  5396.  
  5397. procedure TForm1.InitProfile;
  5398. var
  5399.   i: Integer;
  5400.   str: String;
  5401.   sl: TstringList;
  5402. begin
  5403.   try
  5404.     if frmInfoView.Visible then EBCAState(False);
  5405.     if not CoolTrayIcon1.CycleIcons then
  5406.       Status('Loading profiles...');
  5407.     TxAndWait('AT*EAPN?');
  5408.     sl := TstringList.Create;
  5409.     sl.AddStrings(FRxBuffer);
  5410.     try
  5411.       cbProfile.Items.Clear;
  5412.       FNodeProfiles.DeleteChildren;
  5413.       Explorer.Update;
  5414.       for i := 0 to sl.Count - 2 do begin
  5415.         if pos('*EAPN', sl[i]) = 1 then begin
  5416.           str := Copy(sl[i], 8, length(sl[i]));
  5417.         str := GetToken(str, 1);
  5418.         if FUseUTF8 then str := UTF8Decode(str);
  5419.         cbProfile.Items.Add(str);
  5420.         with Explorer.Items.AddChild(FNodeProfiles,str) do begin
  5421.           ImageIndex := 24;
  5422.         end;
  5423.       end;
  5424.     end;
  5425.     finally
  5426.       sl.Free;
  5427.       if frmExplore.Visible then frmExplore.RootNode := Explorer.Selected;
  5428.     end;
  5429.     TxAndWait('AT*EAPS?');
  5430.     str := Copy(FRxBuffer.Strings[0], 8, length(FRxBuffer.Strings[0]));
  5431.     cbProfile.ItemIndex := StrToInt(GetToken(str, 0)) - 1;
  5432.     if frmInfoView.Visible then EBCAState(True);
  5433.     FNodeProfiles.Expand(False);
  5434.     if not CoolTrayIcon1.CycleIcons then
  5435.       Status('');
  5436.   except
  5437.     Debug('Error getting Profiles');
  5438.   end;
  5439. end;
  5440.  
  5441. procedure TForm1.cbProfileChange(Sender: TObject);
  5442. begin
  5443.   try
  5444.     TxAndWait('AT*EAPS=' + IntToStr(cbProfile.ItemIndex + 1));
  5445.     Status('Profile changed');
  5446.     ShowBaloonInfo('Profile "'+cbProfile.Text+'" activated.');
  5447.     if FAutoProfile then FormStorage1.StoredValue['AutoProfile'] := cbProfile.Text;
  5448.   except
  5449.     Status('Error switching profile');
  5450.   end;
  5451. end;
  5452.  
  5453. procedure TForm1.ScriptEvent(const FunctionName: string;
  5454.   const Params: array of Variant);
  5455. begin
  5456.   if FUseScript and (Trim(FunctionName) <> '') then
  5457.     try
  5458.       if ScriptControl.Code.Count > 0 then
  5459.         CallScriptMethod(FunctionName, Params);
  5460.     except
  5461.       on E: Exception do
  5462.         if not FScriptErrorOccur then
  5463.           Debug('Error: ' + FunctionName + ' exits with error: '+E.Message);
  5464.     end;
  5465. end;
  5466.  
  5467. procedure TForm1.ExplorerDblClick(Sender: TObject);
  5468. var
  5469.   node: TTreeNode;
  5470. begin
  5471.   node := Explorer.Selected;
  5472.   if (node.ImageIndex >= 9) and (node.ImageIndex <= 13) then
  5473.     ActionContactsNewMsg.Execute;
  5474. end;
  5475.  
  5476. procedure TForm1.StatusBarDrawPanel(StatusBar: TStatusBar;
  5477.   Panel: TStatusPanel; const Rect: TRect);
  5478. begin
  5479.   pbRSSI.Parent := StatusBar;
  5480.   pbPower.Parent := StatusBar;
  5481.  
  5482.   if Panel = StatusBar.Panels[2] then begin
  5483.     pbPower.Top := rect.Top + 1;
  5484.     pbPower.Left := rect.Left + 1;
  5485.     pbPower.Width := rect.Right - rect.Left - 3;
  5486.     pbPower.Height := rect.Bottom - rect.Top - 2;
  5487.  
  5488.     if Panel.Text <> '' then begin
  5489.       pbPower.Caption := Panel.Text;
  5490.       pbPower.Visible := True;
  5491.     end
  5492.     else pbPower.Visible := False;
  5493.   end
  5494.   else if Panel = StatusBar.Panels[3] then begin
  5495.     pbRSSI.Top := rect.Top + 1;
  5496.     pbRSSI.Left := rect.Left + 1;
  5497.     pbRSSI.Width := rect.Right - rect.Left - 3;
  5498.     pbRSSI.Height := rect.Bottom - rect.Top - 2;
  5499.  
  5500.     if Panel.Text <> '' then begin
  5501.       pbRSSI.Caption := Panel.Text;
  5502.       pbRSSI.Visible := True;
  5503.     end
  5504.     else pbRSSI.Visible := False;
  5505.   end;
  5506. end;
  5507.  
  5508. procedure TForm1.LMDFMDropFMDragDrop(Sender: TObject; fcount, x,
  5509.   y: Integer; FileList: TStrings);
  5510. var
  5511.   i: Integer;
  5512. begin
  5513.   for i := 0 to FileList.Count - 1 do
  5514.     ObexPutFile(FileList.Strings[i]);
  5515. end;
  5516.  
  5517. procedure TForm1.WSocketOnSessionConnect(Sender: TObject; Error: Word);
  5518. begin
  5519.   if Error = 0 then ComPortAfterOpen(nil)
  5520.   else begin
  5521.     Status('Connection Error (0x' + IntToHex(Error, 8) + ')');
  5522.     FConnectionError := True;
  5523.   end;
  5524. end;
  5525.  
  5526. procedure TForm1.WSocketOnSessionClosed(Sender: TObject; Error: Word);
  5527. begin
  5528.   ActionConnectionDisconnectExecute(nil);
  5529.   ComPortAfterClose(Self);
  5530. end;
  5531.  
  5532. procedure TForm1.WBtSocketDataAvailable(Sender: TObject; Error: Word);
  5533. begin
  5534.   ComPortRxChar(nil, 0);
  5535. end;
  5536.  
  5537. procedure TForm1.DoConnect;
  5538. const
  5539.   SecondAutoConn: boolean = False;
  5540.   procedure ShowConnectVia(What: string);
  5541.   begin
  5542.     if not IsAutoConnect then begin
  5543.       Debug('Establishing new connection via '+What+'.');
  5544.       Debug('Accessing device (may take a while)...');
  5545.     end;
  5546.     if IsAutoConnect and not SecondAutoConn then begin
  5547.       if FSelPhone <> '' then
  5548.         Debug('Auto-connect: Watching for '+FSelPhone+' phone...')
  5549.       else
  5550.         Debug('Auto-connect: Watching for '+PhoneIdentity+' phone...');
  5551.     end;
  5552.     if SecondAutoConn then CoolTrayIcon1.HideBalloonHint;
  5553.     SecondAutoConn := IsAutoConnect;
  5554.   end;
  5555. begin
  5556.   FSelOperator := '';
  5557.   SetPanelText(0,'Searching');
  5558.   try
  5559.     { Clear Activity log only if not auto-connecting }
  5560.     if not IsAutoConnect then
  5561.       GetActivityLogWindow.Memo.Clear;
  5562.     if FConnectionType = 0 then begin // Bluetooth
  5563.       ShowConnectVia('Bluetooth');
  5564.       WBtSocket.Addr := FBTAddress;
  5565.       WBtSocket.Port := FBtPort;
  5566.       WBtSocket.Connect;
  5567.     end
  5568.     else if FConnectionType = 1 then begin // IR
  5569.       ShowConnectVia('IRDA');
  5570.       with WIrSocket.GetConnectedDevices do 
  5571.       try
  5572.         if Count > 0 then begin
  5573.           WIrSocket.DeviceID := Items[0].irdaDeviceID;
  5574.           WIrSocket.Connect;
  5575.         end
  5576.         else 
  5577.           FConnectionError := True;
  5578.       finally
  5579.         Free;
  5580.       end;
  5581.     end
  5582.     else begin // Serial
  5583.       ShowConnectVia('Serial');
  5584.       ComPort.Open;
  5585.     end;
  5586.   except
  5587.     SetPanelText(0,'Disconnected');
  5588.   end;
  5589. end;
  5590.  
  5591. procedure TForm1.DoDisconnect;
  5592. begin
  5593.   { Wait for last command to finish, if needed }
  5594.   if not FAbortDetected and not FTimedout then
  5595.     while FBusy do Application.ProcessMessages;
  5596.   { Save phone database }
  5597.   SaveData;
  5598.  
  5599.   { Restore envirement }
  5600.   if not FExiting and not FAutoConnectionError and IsAutoConnect then
  5601.     DoProximityAway;
  5602.   if FExiting or not FTimedout then
  5603.     DoProximityNear;
  5604.  
  5605.   { Do disconnect now... }
  5606.   EBCALastState := -1;
  5607.   FEBCAKeyMonStopped := False;
  5608.   if FConnectionType = 0 then begin // Bluetooth
  5609.     if WBtSocket.State = wsConnected then WBtSocket.Close;
  5610.   end
  5611.   else if FConnectionType = 1 then begin // IR
  5612.     if WIrSocket.State = wsConnected then WIrSocket.Close;
  5613.   end
  5614.   else begin // Serial
  5615.     ComPort.Close;
  5616.   end;
  5617. end;
  5618.  
  5619.  
  5620. procedure TForm1.WBtSocketChangeState(Sender: TObject; OldState,
  5621.   NewState: TSocketState);
  5622. const
  5623.   aSocketState: array[TSocketState] of string = ('Invalid', 'Opened', 'Bound', 'Connecting', 'Connected', 'Accepting', 'Listening', 'Closed');
  5624. begin
  5625.   Debug('Socket State Changed: ' + aSocketState[NewState]);
  5626. end;
  5627.  
  5628. procedure TForm1.ClearBuffer;
  5629. var
  5630.   Buffer: String;
  5631. begin
  5632.   if FConnectionType = 0 then begin
  5633.     SetLength(buffer, 2048);
  5634.     SetLength(buffer, WBtSocket.Receive(@buffer[1], 2048));
  5635.     WBtSocket.DeleteBufferedData;
  5636.   end
  5637.   else if FConnectionType = 1 then begin
  5638.     SetLength(buffer, 2048);
  5639.     SetLength(buffer, WIrSocket.Receive(@buffer[1], 2048));
  5640.     WIrSocket.DeleteBufferedData;
  5641.   end
  5642.   else begin // Serial
  5643.     SetLength(buffer, 2048);
  5644.     ComPort.ReadStr(buffer, 2048);
  5645.     ComPort.ClearBuffer(True, True);
  5646.   end;
  5647.   if not IsAutoConnect and (Buffer <> '') then Debug('Connection: Discard received garbage.');
  5648. end;
  5649.  
  5650. procedure TForm1.EBCAState(Enable,KeyMonToo: Boolean);
  5651. var
  5652.   State: boolean;  
  5653. begin
  5654.   try
  5655.     State := Enable and CanUseEBCA;
  5656.     if FConnected and not FObex.Connected and not FObexConnecting then begin
  5657.       FEBCAKeyMonStopped := False;
  5658.       if byte(State) <> EBCALastState then begin
  5659.         if State then begin
  5660.           TxAndWait('AT*EBCA=1');
  5661.           if KeyMonToo and FKeyMonitoring then begin
  5662.             TxAndWait('AT+CMER=3,2');
  5663.             FEBCAKeyMonStopped := False;
  5664.           end;
  5665.         end
  5666.         else begin
  5667.           TxAndWait('AT*EBCA=0');
  5668.           if KeyMonToo and FKeyMonitoring then begin
  5669.             TxAndWait('AT+CMER=0,0');
  5670.             FEBCAKeyMonStopped := True;
  5671.           end;
  5672.         end;  
  5673.         EBCALastState := byte(State);
  5674.       end;
  5675.     end
  5676.     else
  5677.       if not FConnected then EBCALastState := -1;
  5678.   except;
  5679.   end;
  5680. end;
  5681.  
  5682. procedure TForm1.ActionToolsEditProfileExecute(Sender: TObject);
  5683. begin
  5684.   if frmInfoView.Visible then EBCAState(False);
  5685.   with TfrmEditProfile.Create(nil) do
  5686.     try
  5687.       ShowModal;
  5688.     finally
  5689.       Free;
  5690.     end;
  5691.   if frmInfoView.Visible then EBCAState(True);
  5692. end;
  5693.  
  5694. procedure TForm1.SetFrameVisible(name: String; visible: Boolean = True);
  5695. //var i,num,size: integer;
  5696.   function GetFrameByName(Name: string): TFrame;
  5697.   begin
  5698.     Result := nil;
  5699.     Name := Trim(UpperCase(Name));
  5700.     if Name = 'EXPLORE' then Result := frmExplore;
  5701.     if Name = 'SIM' then Result := frmSIMEdit;
  5702.     if Name = 'MSG' then Result := frmMsgView;
  5703.     if Name = 'INFO' then Result := frmInfoView;
  5704.     if Name = 'PHONE' then Result := frmSyncPhonebook;
  5705.     if Name = 'SCRIPT' then Result := frmEditor;
  5706.   end;
  5707.   procedure SetFramePrefs(Name: string; Save: boolean = False); // save or restore
  5708.   var
  5709.     i: integer;
  5710.     var Frame: TFrame;
  5711.   begin
  5712.     Frame := GetFrameByName(Name);
  5713.     if Frame = nil then exit;
  5714.     for i := 0 to Frame.ComponentCount-1 do
  5715.       if Frame.Components[i] is TFormStorage then begin
  5716.         with Frame.Components[i] as TFormStorage do
  5717.           if Save then SaveFormPlacement
  5718.             else RestoreFormPlacement;
  5719.       end;
  5720.     if Frame = frmEditor then begin
  5721.       ApplyEditorChanges;
  5722.     end;
  5723.   end;
  5724. begin
  5725.   { Save old frame settings }
  5726.   if FLastShownFrame <> name then begin
  5727.     if name <> '' then SetFrameVisible('');
  5728.     SetFramePrefs(FLastShownFrame,True);
  5729.   end;
  5730.   if name = 'INFO' then
  5731.     FramePanel.BevelOuter := bvLowered
  5732.   else
  5733.     FramePanel.BevelOuter := bvNone;
  5734.   { Set new frame }
  5735.   if name = 'EXPLORE' then begin
  5736.     frmExplore.rootNode := Explorer.Selected;
  5737.     frmExplore.visible := visible;
  5738.     {
  5739.     if (Explorer.Selected <> nil) and (Explorer.Selected.Parent = FNodeObex) then begin
  5740.       num := Explorer.Selected.Count;
  5741.       size := 0;
  5742.       for i := 0 to num-1 do begin
  5743.         size := size + Explorer.Selected.Item[i].StateIndex;
  5744.       end;
  5745.       Status(Format('View %d files(s) in total of %.2n Kb (%.0n bytes)',[num,size / 1024,size * 1.0]));
  5746.     end;
  5747.     }
  5748.   end
  5749.   else if name = 'SIM' then begin
  5750.     frmSIMEdit.visible := visible;
  5751.   end
  5752.   else if name = 'MSG' then begin
  5753.     UpdateMessagePreview;
  5754.     frmMsgView.Visible := visible;
  5755.   end
  5756.   else if name = 'INFO' then begin
  5757.     frmInfoView.Visible := visible;
  5758.     frmInfoView.UpdateWelcomePage(True);
  5759.   end
  5760.   else if name = 'PHONE' then begin
  5761.     frmSyncPhonebook.Visible := visible;
  5762.   end
  5763.   else if name = 'SCRIPT' then begin
  5764.     frmEditor.Visible := visible;
  5765.     frmEditor.Initialize;
  5766.   end
  5767.   else begin
  5768.     { Hide all }
  5769.     frmExplore.visible := False;
  5770.     frmSIMEdit.visible := False;
  5771.     frmMsgView.Visible := False;
  5772.     frmInfoView.Visible := False;
  5773.     frmSyncPhonebook.Visible := False;
  5774.     frmEditor.Visible := False;
  5775.   end;
  5776.   { Load frame settings, if any }
  5777.   if FLastShownFrame <> name then begin
  5778.     FLastShownFrame := name;
  5779.     SetFramePrefs(name);
  5780.   end;  
  5781. end;
  5782.  
  5783. procedure TForm1.ObexConnect(Target: widestring);
  5784. begin
  5785.   RequestConnection;
  5786.   if not FObex.Connected then
  5787.     FObex.Connect(Target);
  5788. end;
  5789.  
  5790. function TForm1.ObexGetObject(Path: Widestring; var stream: TStream; progress: boolean): cardinal;
  5791. var
  5792.   str: TMemoryStream;
  5793. begin
  5794.   str := TMemoryStream.Create;
  5795.   try
  5796.     stream.Size := 0;
  5797.     Result := FObex.GetObject(Path,str);
  5798.     stream.CopyFrom(str,str.Size);
  5799.   finally
  5800.     str.Free;
  5801.   end;
  5802. end;
  5803.  
  5804. function TForm1.ObexPutObject(Path: Widestring; Stream: TStream; progress: boolean): WideString;
  5805. begin
  5806.   Result := FObex.PutObject(Path, stream, progress);
  5807. end;
  5808.  
  5809. procedure TForm1.ObexDisconnect;
  5810. begin
  5811.   if FObex.Connected then
  5812.   try
  5813.     FObex.Disconnect;
  5814.   finally  
  5815.     FlushOK;
  5816.   end;  
  5817. end;
  5818.  
  5819. procedure TForm1.ActionSMSExportExecute(Sender: TObject);
  5820. var
  5821.    Extension: WideString;
  5822. begin
  5823.   SaveDialog1.Filter := 'CSV files (*.csv)|*.csv|XML files (*.xml)|*.xml|Html files (*.html)|*.html';
  5824.   if SaveDialog1.Execute then begin
  5825.      case SaveDialog1.FilterIndex of
  5826.         // sync order with ExportList!
  5827.         1: Extension := '.csv';
  5828.         2: Extension := '.xml';
  5829.         3: Extension := '.html';
  5830.      end;
  5831.      if ExtractFileExt(SaveDialog1.FileName) = Extension then
  5832.         frmMsgView.ExportList(SaveDialog1.FilterIndex, SaveDialog1.FileName)
  5833.      else
  5834.         frmMsgView.ExportList(SaveDialog1.FilterIndex, SaveDialog1.FileName + Extension);
  5835.   end;
  5836. end;
  5837.  
  5838. procedure TForm1.ActionSyncPhonebookExecute(Sender: TObject);
  5839. begin
  5840.   RequestConnection;
  5841.   if frmInfoView.Visible then EBCAState(False);
  5842.   frmInfoView.linkSyncPhonebook.Enabled := False;
  5843.   try
  5844.     if not FStartupOptions.NoObex and not FStartupOptions.NoIRMC and FUseObex then
  5845.       frmSyncPhonebook.btnSYNCClick(nil)
  5846.     else
  5847.       RefreshPhoneBook;
  5848.   finally
  5849.     frmInfoView.linkSyncPhonebook.Enabled := True;
  5850.     if frmInfoView.Visible then EBCAState(True);
  5851.   end;
  5852. end;
  5853.  
  5854. procedure TForm1.ActionSyncLogExecute(Sender: TObject);
  5855. var
  5856.   Dlg: TfrmSyncLog;
  5857. begin
  5858.   Dlg := GetSyncLogWindow;
  5859.   if Dlg.Visible then Dlg.Close else Dlg.Show;
  5860.   FormStorage1.StoredValue['SyncLog'] := Dlg.Visible;
  5861. end;
  5862.  
  5863. function TForm1.WriteSMS(memLocation, PDU: String; Stat: Integer): boolean;
  5864. var
  5865.   GW: string;
  5866.   sms: TSMS;
  5867. begin
  5868.   Result := False;
  5869.   RequestConnection;
  5870.   if frmInfoView.Visible then EBCAState(False);
  5871.   try
  5872.     sms := TSMS.Create;
  5873.     try
  5874.       sms.PDU := pdu;
  5875.       GW := 'AT+CMGW=' + IntToStr(sms.TPLength);
  5876.     finally
  5877.       sms.Free;
  5878.     end;
  5879.     {
  5880.     GW := 'AT+CMGW=' + IntToStr(Round(length(PDU) / 2)-1);
  5881.     { Stat = -1 means default to "received unread" }
  5882.     if Stat <> -1 then GW := GW + ',' + IntToStr(Stat);
  5883.     TxAndWait('AT+CPMS="' + memLocation + '","' + memLocation + '"');
  5884.     TxAndWait(GW, '>');
  5885.     TxAndWait(PDU + #$1A);
  5886.     Debug('Message sent to ' + memLocation);
  5887.     Result := True;
  5888.   except
  5889.     Debug('Message can not be send to ' + memLocation);
  5890.   end;
  5891.   if frmInfoView.Visible then EBCAState(True);
  5892. end;
  5893.  
  5894. procedure TForm1.ActionMissedCallsExecute(Sender: TObject);
  5895. begin
  5896.   frmMissedCalls.Show;
  5897. end;
  5898.  
  5899. procedure TForm1.ActionKeyPadExecute(Sender: TObject);
  5900. begin
  5901.    frmKeyPad.Show;
  5902. end;
  5903.  
  5904. procedure TForm1.RefreshPhoneBook;
  5905. var
  5906.   sl: TStrings;
  5907.   ATMode: boolean;
  5908. begin
  5909.   { this is called in Action-on-execute procedure, so dont call it here 
  5910.   RequestConnection;
  5911.   }
  5912.   ATMode := False;
  5913.   sl := FNodeContactsME.data;
  5914.   if not FStartupOptions.NoObex and not FStartupOptions.NoIRMC and FUseObex then begin
  5915.     { Zdravko: do to read phonebook from the phone,
  5916.       but use sync data to generate it - it's faster }
  5917.     ParsePhonebookListFromSync(sl);
  5918.   end
  5919.   else begin
  5920.     { Obex is not supported, or SyncIRMC is disabled, so use standard AT commands }
  5921.     ATMode := True;
  5922.     frmSIMEdit.CheckForChanges;
  5923.     TxAndWait('AT+CPBS="ME"');
  5924.     DownloadPhonebook;
  5925.     ParsePhonebookList(sl);
  5926.   end;
  5927.   RenderContactList(FNodeContactsME);
  5928.   if ATMode then frmSIMEdit.RenderData;
  5929. end;
  5930.  
  5931. procedure TForm1.ActionExitExecute(Sender: TObject);
  5932. begin
  5933.   FExit := True;
  5934.   FExiting := True;
  5935.   Close;
  5936. end;
  5937.  
  5938. procedure TForm1.ActionContactsExportMEExecute(Sender: TObject);
  5939. var
  5940.    Extension: WideString;
  5941. begin
  5942.   SaveDialog2.Filter := 'vCard files (*.vcf)|*.vcf|CSV files (*.csv)|*.csv|XML files (*.xml)|*.xml|Html files (*.html)|*.html';
  5943.   if SaveDialog2.Execute then begin
  5944.      case SaveDialog2.FilterIndex of
  5945.         // sync with ExportList
  5946.         1: Extension := '.vcf';
  5947.         2: Extension := '.csv';
  5948.         3: Extension := '.xml';
  5949.         4: Extension := '.html';
  5950.      end;
  5951.      if ExtractFileExt(SaveDialog2.FileName) = Extension then
  5952.          frmSyncPhonebook.ExportList(SaveDialog2.FilterIndex, SaveDialog2.FileName)
  5953.      else
  5954.          frmSyncPhonebook.ExportList(SaveDialog2.FilterIndex, SaveDialog2.FileName + Extension);
  5955.   end;
  5956. end;
  5957.  
  5958. procedure TForm1.HandleCCLK(AMsg: String);
  5959. var
  5960.   Year,Hour,Zone,LYear,LHour,LZone: string;
  5961.   TimeZone: TTimeZoneInformation;
  5962.   i,dif: integer;
  5963.   function SecondsDif: integer;
  5964.   var
  5965.     hpc,hhs,mpc,mhs,spc,shs: integer;
  5966.   begin
  5967.     hpc := StrToInt(Copy(LHour,1,2)) * 3600;
  5968.     hhs := StrToInt(Copy(Hour,1,2)) * 3600;
  5969.     mpc := StrToInt(Copy(LHour,4,2)) * 60 + hpc;
  5970.     mhs := StrToInt(Copy(Hour,4,2)) * 60 + hhs;
  5971.     spc := StrToInt(Copy(LHour,7,2)) + mpc;
  5972.     shs := StrToInt(Copy(Hour,7,2)) + mhs;
  5973.     Result := Abs(spc-shs);
  5974.   end;
  5975. begin
  5976.   // +CCLK: "03/12/10,17:18:11+32"
  5977.   // +CCLK: "03/10/27,11:16:30+08"
  5978.   Debug('CLOCK: Checking status...');
  5979.   Delete(AMsg,1,7);
  5980.   i := Pos(',',AMsg);
  5981.   Year := Copy(AMsg,1,i-1);
  5982.   Delete(AMsg,1,i);
  5983.   Delete(Year,1,1); // remove the "
  5984.   if Year[3] = '/' then LYear := 'yy"/"mm"/"dd' else LYear := 'yyyy"/"mm"/"dd';
  5985.   LYear := FormatDateTime(Lyear,Date);
  5986.   i := Pos('+',AMsg);
  5987.   if i = 0 then i := Pos('-',AMsg);
  5988.   if i = 0 then i := Length(AMsg); // Zone doesn't specified
  5989.   Hour := Copy(AMsg,1,i-1);
  5990.   LHour := FormatDateTime('hh":"nn":"ss',Time);
  5991.   Delete(AMsg,1,i-1);
  5992.   Zone := AMsg;
  5993.   Delete(Zone,Length(Zone),1); // remove the "
  5994.   if GetTimeZoneInformation(TimeZone) > TIME_ZONE_ID_UNKNOWN then begin
  5995.     LZone := Format('%.2d',[TimeZone.Bias div 15]);
  5996.     if LZone[1] = '-' then LZone[1] := '+'
  5997.       else if LZone <> '00' then LZone := '-'+LZone
  5998.            else LZone := '+'+LZone;
  5999.     if Zone = '' then LZone := ''; // is this correct ?
  6000.   end
  6001.   else
  6002.     LZone := Zone;
  6003.   Debug('CLOCK: '+Year+','+Hour+Zone+' on Phone');
  6004.   Debug('CLOCK: '+LYear+','+LHour+LZone+' on PC');
  6005.   dif := SecondsDif;
  6006.   FLastClockTZ := Zone;
  6007.   FDoSyncClock := (LYear+LZone <> Year+Zone) or (Copy(Hour,1,5) <> Copy(LHour,1,5)) or (dif > 3);
  6008.   if FDoSyncClock then
  6009.     Debug('CLOCK: Difference more than 3 seconds!')
  6010.   else
  6011.     Debug('CLOCK: OK');
  6012. end;
  6013.  
  6014. procedure TForm1.HandleCPIN(AMsg: String);
  6015. begin
  6016.   Delete(AMsg,1,7);
  6017.   FEmergencyMode := Pos(AMsg,'READY') = 0;
  6018.   if Pos(AMsg,'BLOCKED') <> 0 then Debug('The SIM card is blocked for the user!');
  6019. end;
  6020.  
  6021. procedure TForm1.HandleCNMI(AMsg: String);
  6022. var
  6023.   sl: TStringList;
  6024. begin
  6025.   // +CNMI: (2),(0,1,3),(0,2),(0),(0)
  6026.   Delete(AMsg,1,7);
  6027.   //AMsg := copy(AMsg,1,Pos(',',AMsg)-1);
  6028.   AMsg := StringReplace(Amsg,'),(',');(',[rfReplaceAll]);
  6029.   sl := TStringList.Create;
  6030.   try
  6031.     sl.Delimiter := ';';
  6032.     sl.DelimitedText := AMsg;
  6033.     FUseCNMIMode3 := Pos('3',sl[0]) <> 0;
  6034.     FStatusReport := Pos('1',sl[3]) <> 0; // check the specs for proper value here!
  6035.   finally
  6036.     sl.Free;
  6037.   end;
  6038. end;
  6039.  
  6040. procedure TForm1.HandleCSCS(AMsg: String);
  6041. begin
  6042.   Delete(AMsg,1,7);
  6043.   FSupportedCS := AMsg;
  6044. end;
  6045.  
  6046. procedure TForm1.HandleCLCK(AMsg: String);
  6047. begin
  6048.   Delete(AMsg,1,7);
  6049.   FKeybLocked := AMsg = '1';
  6050.   ActionToolsKeybLock.Enabled := True;
  6051. end;
  6052.  
  6053. procedure TForm1.ParsePhonebookListFromSync(var sl: TStrings);
  6054. var
  6055.   Node :PVirtualNode;
  6056.   contact: PContactData;
  6057.   Name: string;
  6058.   procedure DoAdd(TelType,Tel: string; position: integer);
  6059.   begin
  6060.     { WARNING!! contact.StateIndex meaning should match SIM.imageindex one (new,mod,del) }
  6061.     sl.Add('"' + Name + TelType + '",' + Tel + ',' + IntToStr(position) + ',' + IntToStr(contact.StateIndex));
  6062.   end;
  6063. begin
  6064.   sl.Clear;
  6065.   Node := frmSyncPhonebook.ListContacts.GetFirst;
  6066.   if Node <> nil then
  6067.     repeat
  6068.       contact := frmSyncPhonebook.ListContacts.GetNodeData(Node);
  6069.       Name := contact.name;
  6070.       if contact.surname <> '' then Name := Name + ' ' + contact.surname;
  6071.       if contact.home  <> '' then DoAdd('/H',contact.home,contact.Position.home);
  6072.       if contact.work  <> '' then DoAdd('/W',contact.work,contact.Position.work);
  6073.       if contact.cell  <> '' then DoAdd('/M',contact.cell,contact.Position.cell);
  6074.       if contact.fax   <> '' then DoAdd('/F',contact.fax,contact.Position.fax);
  6075.       if contact.other <> '' then DoAdd('/O',contact.other,contact.Position.other);
  6076.       Application.ProcessMessages;
  6077.       Node := frmSyncPhonebook.ListContacts.GetNext(Node);
  6078.     until Node = nil;
  6079.   TStringList(sl).Sort;
  6080. end;
  6081.  
  6082. procedure TForm1.ActionToolsPostBookmarkExecute(Sender: TObject);
  6083. var
  6084.   bt,bu: WideString;
  6085.   {sl: TStrings;
  6086.   stream: TStream;}
  6087. begin
  6088.   with frmBookmark do begin
  6089.     if ShowModal = mrOK then begin
  6090.       if Memo.Text <> '' then begin
  6091.         {
  6092.         sl := TStringList.Create;
  6093.         try
  6094.           sl.Add('BEGIN:VBKM');
  6095.           sl.Add('VERSION:1.0');
  6096.           sl.Add('TITLE:' + Edit1.Text);
  6097.           sl.Add('URL:' + Memo.Text);
  6098.           sl.Add('BEGIN:ENV');
  6099.           sl.Add('X-IRMC-URL;QUOTED-PRINTABLE:=');
  6100.           sl.Add('[InternetShortcut] =');
  6101.           sl.Add('URL:' + Memo1.Text);
  6102.           sl.Add('END:ENV');
  6103.           sl.Add('END:VBKM');
  6104.  
  6105.           stream := TMemoryStream.Create;
  6106.           try
  6107.             sl.SaveToStream(stream);
  6108.  
  6109.             RequestConnection;
  6110.             FObex.PutObject('fma.url', stream, true);
  6111.           finally
  6112.             stream.Free;
  6113.             FlushOK;
  6114.           end;  
  6115.         finally
  6116.           sl.Free;
  6117.         end;
  6118.         }
  6119.         RequestConnection;
  6120.         if FUseUTF8 then begin
  6121.           bu := UTF8Encode(Memo.Text);
  6122.           bt := UTF8Encode(Edit1.Text);
  6123.         end
  6124.         else begin
  6125.           bu := Memo.Text;
  6126.           bt := Edit1.Text;
  6127.         end;
  6128.         TxAndWait('AT*EWBA=0,"'+bu+'","'+bt+'"');
  6129.         InitBookmarks;
  6130.       end
  6131.       else begin
  6132.         Status('Nothing to post');
  6133.       end;
  6134.     end;
  6135.   end;
  6136. end;
  6137.  
  6138. procedure TForm1.ActionObexReadyUpdate(Sender: TObject);
  6139. begin
  6140.   with (Sender as TAction) do begin
  6141.     Enabled := not FBusy and not FStartupOptions.NoObex and FUseObex and FConnected;
  6142.   end;  
  6143. end;
  6144.  
  6145. procedure TForm1.ActionToolsDownloadUpdate(Sender: TObject);
  6146. begin
  6147.   ActionToolsDownload.Enabled := FConnected and not FBusy and not FStartupOptions.NoObex and FUseObex and
  6148.     ((Explorer.Selected <> nil) and (Explorer.Selected.ImageIndex in [27,36..38])) or // only for obex folder items
  6149.     (frmExplore.Visible and (frmExplore.ListItems.SelectedCount <> 0) and (Explorer.Selected.Parent = FNodeObex));
  6150. end;
  6151.  
  6152. procedure TForm1.ActionToolsUploadExecute(Sender: TObject);
  6153. var
  6154.   i: integer;
  6155.   frmConnect: TfrmConnect;
  6156. begin
  6157.   if OpenDialog1.Execute then begin
  6158.     ObexConnect;
  6159.     try
  6160.       frmConnect := GetProgressDialog;
  6161.       if CanShowProgress then
  6162.         frmConnect.ShowProgress(FProgressLongOnly);
  6163.       try
  6164.         for i := 0 to OpenDialog1.Files.Count-1 do begin
  6165.           try
  6166.             ObexPutFile(OpenDialog1.Files[i]);
  6167.           except
  6168.             on e: exception do
  6169.               if FObex.IsAborted then raise
  6170.               else Status(e.Message);
  6171.           end;
  6172.         end;
  6173.       finally
  6174.         FreeProgressDialog;
  6175.       end;
  6176.     finally
  6177.       ObexDisconnect;
  6178.     end;
  6179.   end;
  6180. end;
  6181.  
  6182. procedure TForm1.ActionToolsEditProfileUpdate(Sender: TObject);
  6183. begin
  6184.   ActionToolsEditProfile.Enabled := not FBusy and FConnected and (cbProfile.Items.Count <> 0);
  6185.   cbProfile.Enabled := ActionToolsEditProfile.Enabled;
  6186. end;
  6187.  
  6188. procedure TForm1.ActionConnectionConnectUpdate(Sender: TObject);
  6189. begin
  6190.   ActionConnectionConnect.Enabled := not FConnected;
  6191. end;
  6192.  
  6193. procedure TForm1.ActionConnectionDisconnectUpdate(Sender: TObject);
  6194. begin
  6195.   ActionConnectionDisconnect.Enabled := FConnected;
  6196. end;
  6197.  
  6198. procedure TForm1.ActionConnectionToggleUpdate(Sender: TObject);
  6199. begin
  6200.   ActionConnectionToggle.Checked := FConnected;
  6201.   ActionConnectionToggle.ImageIndex := 28 + byte(not FConnected);
  6202.   ActionConnectionToggle.Enabled := not FConnectingStarted or FConnectingComplete;
  6203. end;
  6204.  
  6205. function TForm1.ObexGetObject(Path: Widestring; var Where: TStringList; progress: boolean;
  6206.   FriendlyName: string): cardinal;
  6207. var
  6208.   str: TMemoryStream;
  6209. begin
  6210.   str := TMemoryStream.Create;
  6211.   try
  6212.     Where.Clear;
  6213.     Result := FObex.GetObject(Path,str,progress,FriendlyName);
  6214.     Where.LoadFromStream(str);
  6215.   finally
  6216.     str.Free;
  6217.   end;
  6218. end;
  6219.  
  6220. procedure TForm1.StartupInitialize;
  6221. var
  6222.   i: Integer;
  6223.   dlg: TfrmStatusDlg;
  6224. begin
  6225.   if FNotFirstInstance then exit;
  6226.   if Application.ShowMainForm then
  6227.     dlg := ShowStatusDlg('Initializing FMA...')
  6228.   else
  6229.     dlg := nil;
  6230.   try
  6231.     ActivityLog('Starting...');
  6232.     ComPortAfterClose(nil);
  6233.  
  6234.     { Check for debug switches }
  6235.     frmDebug := Nil;
  6236.     for i := 1 to ParamCount do begin
  6237.       if Uppercase(ParamStr(i)) = '-DEBUG' then begin
  6238.         frmDebug := TfrmDebug.Create(Self);
  6239.         frmDebug.AlphaBlendValue := FAlphaDebug;
  6240.         frmDebug.AlphaBlend := True;
  6241.         DebugTools1.Visible := True;
  6242.         ActivityLog('Debug mode enabled (AT commands).');
  6243.       end;
  6244.       if Uppercase(ParamStr(i)) = '-DEBUGOBEX' then begin
  6245.         FObex.debugobex := True;
  6246.         ActivityLog('Debug mode enabled (OBEX hex).');
  6247.       end;
  6248.     end;
  6249.  
  6250.     { Create explorer tree }
  6251.     Explorer.Items.GetFirstNode.Expand(True);
  6252.     Explorer.Selected := Explorer.Items.GetFirstNode;
  6253.  
  6254.     for i := 0 to Explorer.Items.Count - 1 do begin
  6255.       with Explorer do begin
  6256.         // Locate Contacts Folders
  6257.         if (Items[i].StateIndex and $F00000) = $100000 then begin
  6258.           if (Items[i].StateIndex and $0C0000) = $000000 then FNodeContactsME := Items[i];
  6259.           if (Items[i].StateIndex and $0C0000) = $040000 then FNodeContactsSM := Items[i];
  6260.           //if (Items[i].StateIndex and $0C0000) = $080000 then FNodeContactsSYNC := Items[i];
  6261.         end;
  6262.  
  6263.         // Locate SMS Folders
  6264.         if (Items[i].StateIndex and $F00000) = $200000 then begin
  6265.           if (Items[i].StateIndex and $0F0000) = $010000 then begin
  6266.             FNodeMsgInbox := Items[i];
  6267.             // Debug('Found Inbox');
  6268.           end;
  6269.  
  6270.           if (Items[i].StateIndex and $0F0000) = $020000 then begin
  6271.             FNodeMsgSent := Items[i];
  6272.             // Debug('Found Sent Items');
  6273.           end;
  6274.  
  6275.           if (Items[i].StateIndex and $0F0000) = $0A0000 then begin
  6276.             FNodeMsgOutbox := Items[i];
  6277.             // Debug('Found Outbox');
  6278.           end;
  6279.  
  6280.           if (Items[i].StateIndex and $0F0000) = $0B0000 then begin
  6281.             FNodeMsgArchive := Items[i];
  6282.             // Debug('Found Archive');
  6283.           end;
  6284.  
  6285.           if (Items[i].StateIndex and $0F0000) = $0C0000 then begin
  6286.             FNodeMsgDrafts := Items[i];
  6287.             // Debug('Found Drafts');
  6288.           end;
  6289.         end;
  6290.  
  6291.         // Locate Obex Folders
  6292.         if (Items[i].StateIndex and $F00000) = $500000 then
  6293.           FNodeObex := Items[i];
  6294.  
  6295.         // Locate Profiles Folder
  6296.         if (Items[i].StateIndex and $F00000) = $700000 then
  6297.           FNodeProfiles := Items[i];
  6298.  
  6299.         // Locate Calls root Folder
  6300.         if (Items[i].StateIndex and $F00000) = $400000 then
  6301.           case (Items[i].StateIndex and $0F0000) shr 16 of
  6302.             0: FNodeCalls := Items[i];
  6303.             1: FNodeCallsIn := Items[i];
  6304.             2: FNodeCallsOut := Items[i];
  6305.             3: FNodeCallsMissed := Items[i];
  6306.           end;
  6307.  
  6308.         // Locate Groups Folder
  6309.         if (Items[i].StateIndex and $F00000) = $800000 then
  6310.           FNodeGroups := Items[i];
  6311.  
  6312.         // Locate Organizer Folder
  6313.         if (Items[i].StateIndex and $F00000) = $900000 then 
  6314.           FNodeOrganizer := Items[i];
  6315.         if (Items[i].StateIndex and $F00000) = $300000 then begin
  6316.           case (Items[i].StateIndex and $0F0000) shr 16 of
  6317.             1: ; // notes
  6318.             2: FNodeBookmarks :=Items[i];
  6319.             3: ; // alarms
  6320.             4: ; // calendar
  6321.           end;
  6322.         end;
  6323.  
  6324.         // Locate Scripts Folder
  6325.         if (Items[i].StateIndex and $F00000) = $A00000 then
  6326.           FNodeScripts := Items[i];
  6327.       end;
  6328.  
  6329.     end;
  6330.  
  6331.     { Create database storage }
  6332.     FNodeMsgInbox.Data := TStringList.Create;
  6333.     FNodeMsgOutbox.Data := TStringList.Create;
  6334.     FNodeMsgSent.Data := TStringList.Create;
  6335.     FNodeMsgArchive.Data := TStringList.Create;
  6336.     FNodeMsgDrafts.Data := TStringList.Create;
  6337.     FNodeContactsME.Data := TStringList.Create;
  6338.     FNodeContactsSM.Data := TStringList.Create;
  6339.     FNodeCallsIn.Data := TStringList.Create;
  6340.     FNodeCallsOut.Data := TStringList.Create;
  6341.     FNodeCallsMissed.Data := TStringList.Create;
  6342.     FNodeBookmarks.Data := TStringList.Create;
  6343.  
  6344.     { Load database files }
  6345.     if dlg <> nil then dlg.Status('Loading Profile Database...');
  6346.     try
  6347.       if not LoadPhoneDataFiles then
  6348.         ActivityLog('ERROR: Could not initialize phone database (load failed)');
  6349.     except
  6350.     end;
  6351.  
  6352.     if dlg <> nil then dlg.Status('Building Contact Lists...');
  6353.     SetFrameVisible('INFO');
  6354.     RenderContactList;
  6355.  
  6356.     { Load script, if any }
  6357.     if dlg <> nil then dlg.Status('Initializing Script Engine...');
  6358.     ScriptInitialize;
  6359.  
  6360.     { Set startup folder, if specified }
  6361.     ViewInitialize;
  6362.     //FNodeOrganizer.Collapse(True); // not implemented, so hide it
  6363.   finally
  6364.     if dlg <> nil then dlg.Free;
  6365.     CoolTrayIcon1.IconVisible := True;
  6366.     Timer1.Enabled := True;
  6367.   end;
  6368. end;
  6369.  
  6370. procedure TForm1.ActionMissedCallsUpdate(Sender: TObject);
  6371. begin
  6372.   ActionMissedCalls.Enabled := (frmMissedCalls <> nil) and (frmMissedCalls.RecentMissedCalls <> 0);
  6373.   if not ActionMissedCalls.Enabled then
  6374.     ActionMissedCalls.ImageIndex := 16;
  6375. end;
  6376.  
  6377. procedure TForm1.FloatingRectangles(Minimizing, OverrideUserSettings: Boolean);
  6378. {
  6379. var
  6380.   RectFrom, RectTo: TRect;
  6381.   GotRectTo: Boolean;
  6382.   abd: TAppBarData;
  6383.   HTaskbar, HTrayWnd: HWND;
  6384.   ResetRegistry: Boolean;
  6385.   ai: TAnimationInfo;
  6386.  
  6387.   procedure SetAnimation(Animation: Boolean);
  6388.   begin
  6389.     FillChar(ai, SizeOf(ai), 0);
  6390.     ai.cbSize := SizeOf(ai);
  6391.     if Animation then
  6392.       ai.iMinAnimate := $C0
  6393.     else
  6394.       ai.iMinAnimate := 0;
  6395.     SystemParametersInfo(SPI_SETANIMATION, SizeOf(ai), @ai, SPIF_SENDCHANGE);
  6396.   end;
  6397. }
  6398. begin
  6399.   // temporary disabled, because it results double animation:
  6400.   // one to taskbar and one to tray area, not so good :(
  6401.  
  6402.   { TODO: Disable Windows animation for this window, and then use FloatingRectangles }
  6403.  
  6404.   (*
  6405.   // Check if user wants window animation
  6406.   FillChar(ai, SizeOf(ai), 0);
  6407.   ai.cbSize := SizeOf(ai);
  6408.   if not SystemParametersInfo(SPI_GETANIMATION, SizeOf(ai), @ai, 0) then
  6409.     exit;
  6410.   ResetRegistry := False;
  6411.   if OverrideUserSettings then begin
  6412.     if ai.iMinAnimate = 0 then begin
  6413.       // Temporarily enable window animation
  6414.       ResetRegistry := True;
  6415.       SetAnimation(True);
  6416.     end;
  6417.   end
  6418.   else
  6419.     if ai.iMinAnimate = 0 then exit;
  6420.  
  6421.   RectFrom := BoundsRect;
  6422.   GotRectTo := False;
  6423.  
  6424.   // Get the traybar's bounding rectangle
  6425.   HTaskbar := FindWindow('Shell_TrayWnd', nil);
  6426.   if HTaskbar <> 0 then
  6427.   begin
  6428.     HTrayWnd := FindWindowEx(HTaskbar, 0, 'TrayNotifyWnd', nil);
  6429.     if HTrayWnd <> 0 then
  6430.       if GetWindowRect(HTrayWnd, RectTo) then
  6431.         GotRectTo := True;
  6432.   end;
  6433.  
  6434.   // If that fails, invent a rectangle in the corner where the traybar is
  6435.   if not GotRectTo then
  6436.   begin
  6437.     FillChar(abd, SizeOf(abd), 0);
  6438.     abd.cbSize := SizeOf(abd);
  6439.     if SHAppBarMessage(ABM_GETTASKBARPOS, abd) = 0 then Exit;
  6440.     with Screen, abd.rc do
  6441.       if (Top > 0) or (Left > 0) then
  6442.         RectTo := Rect(Width-32, Height-32, Width, Height)
  6443.       else if (Bottom < Height) then
  6444.         RectTo := Rect(Width-32, 0, Width, 32)
  6445.       else if (Right < Width) then
  6446.         RectTo := Rect(0, Height-32, 32, Height);
  6447.   end;
  6448.  
  6449.   if Minimizing then
  6450.     DrawAnimatedRects(Handle, IDANI_CAPTION, RectFrom, RectTo)
  6451.   else
  6452.     DrawAnimatedRects(Handle, IDANI_CAPTION, RectTo, RectFrom);
  6453.  
  6454.   if ResetRegistry then
  6455.     SetAnimation(False);               // Disable window animation
  6456.   *)  
  6457. end;
  6458.  
  6459. procedure TForm1.ActionWindowMinimizeExecute(Sender: TObject);
  6460. begin
  6461.   Application.Minimize;
  6462. end;
  6463.  
  6464. procedure TForm1.ShowBaloonInfo(Text: string; Timeout: TBalloonHintTimeOut);
  6465. begin
  6466.   FLastBaloonMessagePDU := '';
  6467.   CoolTrayIcon1.ShowBalloonHint(Application.Title,Text,bitInfo,Timeout);
  6468.   Debug(Text);
  6469. end;
  6470.  
  6471. procedure TForm1.FormDestroy(Sender: TObject);
  6472. begin
  6473.   try
  6474.     ClearExplorerViews;
  6475.     CoolTrayIcon1.IconVisible := False;
  6476.  
  6477.     { Free views }
  6478.     FreeAndNil(frmMsgView);
  6479.     FreeAndNil(frmSIMEdit);
  6480.     FreeAndNil(frmInfoView);
  6481.     FreeAndNil(frmSyncPhonebook);
  6482.     FreeAndNil(frmExplore);
  6483.     FreeAndNil(frmEditor);
  6484.  
  6485.     { Free database storage }
  6486.     TStringList(FNodeMsgInbox.Data).Free;
  6487.     FNodeMsgInbox := nil;
  6488.     TStringList(FNodeMsgOutbox.Data).Free;
  6489.     FNodeMsgOutbox := nil;
  6490.     TStringList(FNodeMsgSent.Data).Free;
  6491.     FNodeMsgSent := nil;
  6492.     TStringList(FNodeMsgArchive.Data).Free;
  6493.     FNodeMsgArchive := nil;
  6494.     TStringList(FNodeMsgDrafts.Data).Free;
  6495.     FNodeMsgDrafts := nil;
  6496.     TStringList(FNodeContactsME.Data).Free;
  6497.     FNodeContactsME := nil;
  6498.     TStringList(FNodeContactsSM.Data).Free;
  6499.     FNodeContactsSM := nil;
  6500.     TStringList(FNodeCallsIn.Data).Free;
  6501.     FNodeCallsIn := nil;
  6502.     TStringList(FNodeCallsOut.Data).Free;
  6503.     FNodeCallsOut := nil;
  6504.     TStringList(FNodeCallsMissed.Data).Free;
  6505.     FNodeCallsMissed := nil;
  6506.     TStringList(FNodeBookmarks.Data).Free;
  6507.     FNodeBookmarks := nil;
  6508.  
  6509.     { Free local variables }
  6510.     FreeAndNil(FObex);
  6511.     FreeAndNil(FRxBuffer);
  6512.     FreeAndNil(FNewMessageList);
  6513.     FreeAndNil(FLookupList);
  6514.     FreeAndNil(FFavoriteRecipients);
  6515.     FreeAndNil(FFavoriteCalls);
  6516.  
  6517. {$IFNDEF VER150}
  6518.     ThemeManager1.Free;
  6519. {$ENDIF}
  6520.  
  6521.   finally
  6522.     { Close handles }
  6523.     CloseHandle(FWaitCompleteEvent);
  6524.     CloseHandle(FWaitCompleteIsBusyEvent);
  6525.     CloseHandle(FFmaMutex);
  6526.   end;
  6527. end;
  6528.  
  6529. procedure TForm1.ActionToolsChangeProfileExecute(Sender: TObject);
  6530. begin
  6531.   cbProfile.ItemIndex := cbProfile.Items.IndexOf(Explorer.Selected.Text);
  6532.   cbProfileChange(cbProfile);
  6533. end;
  6534.  
  6535. procedure TForm1.ActionToolsChangeProfileUpdate(Sender: TObject);
  6536. begin
  6537.   ActionToolsChangeProfile.Enabled := not FBusy and FConnected and
  6538.     (Explorer.Selected <> nil) and (Explorer.Selected.ImageIndex = 24) and (Explorer.Selected.Text <> cbProfile.Text)
  6539. end;
  6540.  
  6541. procedure TForm1.Button3Click(Sender: TObject);
  6542. begin
  6543.   Memo3.Lines.Add(cbTerminal.Text);
  6544.   try
  6545.     TxAndWait(cbTerminal.Text);
  6546.     Memo3.Lines.AddStrings(FRxBuffer);
  6547.     if cbTerminal.Items.IndexOf(cbTerminal.Text) = -1 then
  6548.       cbTerminal.Items.Insert(0,cbTerminal.Text);
  6549.     cbTerminal.Text := '';
  6550.   except
  6551.     on e: Exception do Memo3.Lines.Add(e.Message);
  6552.   end;
  6553. end;
  6554.  
  6555. procedure TForm1.InitGroups;
  6556. var
  6557.   i,j,typ: Integer;
  6558.   str,num,who,number: String;
  6559.   sl,it: TStringList;
  6560.   grp,cnt,member: TTntTreeNode;
  6561.   IsMEModified: boolean;
  6562.   function GetName(From: string; index: integer; var Number: string): string;
  6563.   var
  6564.     root: TTntTreeNode;
  6565.     i,j: integer;
  6566.     s: string;
  6567.   begin
  6568.     Result := '(Unknown)';
  6569.     { Each contact number's StateIndex contains its position in phonebook }
  6570.     if From <> '' then begin
  6571.       s := '';
  6572.       if From = 'ME' then root := FNodeContactsME else root := FNodeContactsSM;
  6573.       for i := 0 to root.Count-1 do begin
  6574.         for j := 0 to root.Item[i].Count-1 do
  6575.           if root.Item[i].Item[j].StateIndex = index then begin
  6576.             s := root.Item[i].Text;
  6577.             Number := root.Item[i].Item[j].Text;
  6578.             break;
  6579.           end;
  6580.         if s <> '' then break;
  6581.         Application.ProcessMessages;
  6582.         if FAbortDetected then break;
  6583.       end;
  6584.       if s = '' then begin
  6585.         s := LocatePBName(From,index,Number);
  6586.         if s <> '' then IsMEModified := True;
  6587.       end;
  6588.       if s <> '' then begin
  6589.         Result := s;
  6590.       end;
  6591.     end
  6592.     { Each group's StateIndex contains its phone index }
  6593.     else begin
  6594.       root := FNodeGroups;
  6595.       for i := 0 to root.Count-1 do
  6596.         if root.Item[i].StateIndex = index then begin
  6597.           Result := root.Item[i].Text;
  6598.           break;
  6599.         end;
  6600.     end;
  6601.   end;
  6602. begin
  6603.   IsMEModified := False;
  6604.   if Assigned(FNodeGroups) then
  6605.   try
  6606.     if frmInfoView.Visible then EBCAState(False);
  6607.     if not CoolTrayIcon1.CycleIcons then
  6608.       Status('Loading groups...');
  6609.     FNodeGroups.DeleteChildren;
  6610.     Explorer.Update;
  6611.     { Check if all contacts have a position associated with them,
  6612.       so we can find group entries correctly.
  6613.     if FNodeContactsME.Count = 0 then begin
  6614.       if MessageDlg('The Phonebook is empty. Should we download it now?',
  6615.         mtConfirmation,[mbYes,mbNo],0) = ID_YES then
  6616.         frmSyncPhonebook.btnSYNCClick(nil);
  6617.     end
  6618.     else
  6619.       if frmSyncPhonebook.UpdatePositions then
  6620.         RefreshPhoneBook;
  6621.     { Retrieve groups now }
  6622.     sl := TStringList.Create;
  6623.     it := TStringList.Create;
  6624.     try
  6625.       TxAndWait('AT*ESGR=?');
  6626.       TxAndWait('AT*ESGR');
  6627.       sl.AddStrings(FRxBuffer);
  6628.       for i := 0 to sl.Count - 2 do begin
  6629.         if pos('*ESGR', sl[i]) = 1 then begin
  6630.           str := Copy(sl[i], 8, length(sl[i]));
  6631.           num := GetToken(str, 0);
  6632.           str := GetToken(str, 1); // folder name
  6633.           if FUseUTF8 then str := UTF8Decode(str);
  6634.           Debug('Building group '+str+'...');
  6635.           grp := Explorer.Items.AddChild(FNodeGroups,str);
  6636.           with grp do begin
  6637.             ImageIndex := 58;
  6638.             StateIndex := StrToInt(num);
  6639.             TxAndWait('AT*EGIR='+num);
  6640.             it.Clear; // clear items frmo previous group, 10x to Mindstormpt 
  6641.             it.AddStrings(FRxBuffer);
  6642.             for j := 0 to it.Count - 2 do begin
  6643.               if pos('*EGIR', it[j]) = 1 then begin
  6644.                 str := Copy(it[j], 8, length(it[j]));
  6645.                 num := GetToken(str, 0);
  6646.                 typ := StrToInt(GetToken(str, 1));
  6647.                 str := GetToken(str, 2); // item index
  6648.                 { if it's number index get name and number (from ME) }
  6649.                 if typ = 2 then who := GetName('ME',StrToInt(str),number);
  6650.                 { check if member is already added }
  6651.                 member := nil;
  6652.                 cnt := grp.getFirstChild;
  6653.                 while cnt <> nil do begin
  6654.                   if WideCompareText(cnt.Text,who) = 0 then begin
  6655.                     member := cnt;
  6656.                     break;
  6657.                   end;
  6658.                   cnt := grp.GetNextChild(cnt);
  6659.                 end;
  6660.                 if member = nil then begin
  6661.                   { nop, add it now }
  6662.                   member := Explorer.Items.AddChild(grp,str); // str is an index here, not a name!
  6663.                   member.ImageIndex := 8;
  6664.                   member.StateIndex := StrToInt(num);
  6665.                 end;
  6666.                 { add member data }
  6667.                 with member do begin
  6668.                   case typ of
  6669.                     0: ImageIndex := 26; // group, will get name later
  6670.                     1: Text := 'Contact #'+str; // contact, how to handle this ???
  6671.                     2: begin
  6672.                          Text := who;
  6673.                          with Explorer.Items.AddChild(member,number) do ImageIndex := 13; // add number under name in Explorer
  6674.                        end;
  6675.                   end;
  6676.                 end;
  6677.                 if FAbortDetected then break;
  6678.               end;
  6679.             end;
  6680.           end;
  6681.         end;
  6682.       end;
  6683.       { Update group names }
  6684.       for i := 0 to FNodeGroups.Count-1 do
  6685.         for j := 0 to FNodeGroups.Item[i].Count-1 do
  6686.           if FNodeGroups.Item[i].Item[j].ImageIndex = 26 then begin
  6687.             Text := GetName('',StrToInt(Text),num);
  6688.           end;
  6689.       FNodeGroups.Expand(False);
  6690.       if not CoolTrayIcon1.CycleIcons then
  6691.         Status('');
  6692.     finally
  6693.       sl.Free;
  6694.       it.Free;
  6695.       if frmInfoView.Visible then EBCAState(True);
  6696.       if frmExplore.Visible then frmExplore.RootNode := Explorer.Selected; 
  6697.     end;
  6698.     if IsMEModified then UpdateMEPhonebook;
  6699.   except
  6700.     Debug('Error getting Groups');
  6701.   end;
  6702. end;
  6703.  
  6704. procedure TForm1.DoRemoveGroupMemberOrFile;
  6705. var
  6706.   GID,PID: integer;
  6707.   gname,cname,s: WideString;
  6708.   FromView: boolean;
  6709.   Item: PExploreItem;
  6710.   SelNode,Node,DelNode: PVirtualNode;
  6711.   frmConnect: TfrmConnect;
  6712.   Multiselect: boolean;
  6713.   procedure ReindexGroup;
  6714.   var
  6715.     i,j: integer;
  6716.     Root,DelNode: TTntTreeNode;
  6717.     procedure FixIt;
  6718.     begin
  6719.       Root.Item[i].StateIndex := j;
  6720.       inc(j);
  6721.     end;
  6722.   begin
  6723.     DelNode := nil;
  6724.     j := 1;
  6725.     if FromView then Root := Explorer.Selected
  6726.       else Root := Explorer.Selected.Parent;
  6727.     for i := 0 to Root.Count-1 do
  6728.       if FromView then
  6729.         if WideCompareText(Root.Item[i].Text,cname) <> 0 then
  6730.           FixIt
  6731.         else
  6732.           DelNode := Root.Item[i] // we have to delete explorer entry too
  6733.       else
  6734.         if Root.Item[i] <> Explorer.Selected then FixIt;
  6735.     if Assigned(DelNode) then DelNode.Delete;
  6736.   end;
  6737.   procedure ReindexFolder;
  6738.   var
  6739.     i: integer;
  6740.     Root,DelNode: TTntTreeNode;
  6741.   begin
  6742.     if FromView then begin
  6743.       DelNode := nil;
  6744.       Root := Explorer.Selected;
  6745.       for i := 0 to Root.Count-1 do
  6746.         if WideCompareText(Root.Item[i].Text,cname) = 0 then begin
  6747.           DelNode := Root.Item[i]; // we have to delete explorer entry too
  6748.           break;
  6749.         end;
  6750.       if Assigned(DelNode) then DelNode.Delete;
  6751.     end;
  6752.   end;
  6753. begin
  6754.   SelNode := frmExplore.ListItems.FocusedNode;
  6755.   { Delete from Groups }
  6756.   if (Explorer.Selected.Parent = FNodeGroups) or (Explorer.Selected.Parent.Parent = FNodeGroups) then begin
  6757.     FromView := frmExplore.Visible and frmExplore.ListItems.Focused and (SelNode.Dummy = 8); // for contacts only
  6758.     if FromView then begin
  6759.       Item := frmExplore.ListItems.GetNodeData(SelNode);
  6760.       GID := Explorer.Selected.StateIndex;
  6761.       PID := StrToInt(Item.param);
  6762.       gname := Explorer.Selected.Text;
  6763.       cname := Item.name;
  6764.     end
  6765.     else begin
  6766.       GID := Explorer.Selected.Parent.StateIndex;
  6767.       PID := Explorer.Selected.StateIndex;
  6768.       gname := Explorer.Selected.Parent.Text;
  6769.       cname := Explorer.Selected.Text;
  6770.     end;
  6771.     if MessageDlg('Removing "'+cname+'" from group "'+gname+'". Do you wish to continue?',
  6772.       mtConfirmation,[mbYes,mbNo],0) <> ID_YES then
  6773.       exit;
  6774.     TxAndWait('AT*ESDI='+IntToStr(GID)+','+IntToStr(PID));
  6775.     ReindexGroup; // Delete node from Explorer too, and reindex other items
  6776.     if FromView then begin
  6777.       frmExplore.ListItems.DeleteNode(SelNode);
  6778.       frmExplore.RootNode := Explorer.Selected; // update view
  6779.     end
  6780.     else
  6781.       Explorer.Selected.Delete;
  6782.   end;
  6783.   { Delete from Obex files }
  6784.   if (Explorer.Selected.Parent = FNodeObex) or (Explorer.Selected.Parent.Parent = FNodeObex) then begin
  6785.     FromView := frmExplore.Visible and frmExplore.ListItems.Focused and (SelNode.Dummy in [27,36..38]);
  6786.     Multiselect := FromView and (frmExplore.ListItems.SelectedCount > 1); // [27,36..38] = for obex files only, on change see TfrmExplore.Set_RootNode()
  6787.     if FromView then begin
  6788.       Item := frmExplore.ListItems.GetNodeData(SelNode);
  6789.       gname := Explorer.Selected.Text;
  6790.       cname := Item.name;
  6791.     end
  6792.     else begin
  6793.       gname := Explorer.Selected.Parent.Text;
  6794.       cname := Explorer.Selected.Text;
  6795.     end;
  6796.     if Multiselect then
  6797.       s := IntToStr(frmExplore.ListItems.SelectedCount) + ' items'
  6798.     else
  6799.       s := '"'+cname+'"';
  6800.     if MessageDlg('Are you sure you want to delete '+s+' from "'+gname+'"?',
  6801.       mtConfirmation,[mbYes,mbNo],0) = ID_YES then begin
  6802.  
  6803.       frmConnect := nil;
  6804.       try
  6805.         { Multiple files selected? }
  6806.         if Multiselect then
  6807.         try
  6808.           frmExplore.ListItems.Enabled := False;
  6809.           frmConnect := GetProgressDialog;
  6810.           if CanShowProgress then
  6811.             frmConnect.ShowProgress(FProgressLongOnly);
  6812.           frmConnect.SetDescr('Deleting files');
  6813.           Status('Deleting files');
  6814.           { Yes, delete rest of the files }
  6815.           Node := frmExplore.ListItems.GetFirst;
  6816.           while Node <> nil do begin
  6817.             DelNode := nil;
  6818.             if frmExplore.ListItems.Selected[Node] then begin
  6819.               Item := frmExplore.ListItems.GetNodeData(Node);
  6820.               cname := Item.name;
  6821.               frmConnect.SetDescr('Deleting '+cname+'...');
  6822.               ObexPutFile(gname+'/'+cname,True);
  6823.               ReindexFolder;
  6824.               DelNode := Node;
  6825.             end;
  6826.             Node := frmExplore.ListItems.GetNext(Node);
  6827.             if Assigned(DelNode) then
  6828.               frmExplore.ListItems.DeleteNode(DelNode);
  6829.           end;
  6830.         finally
  6831.           frmExplore.ListItems.Enabled := True;
  6832.           frmExplore.RootNode := Explorer.Selected;
  6833.         end
  6834.         else begin
  6835.           ObexPutFile(gname+'/'+cname,True);
  6836.           ReindexFolder; // Delete node from Explorer too
  6837.           if FromView then begin
  6838.             frmExplore.ListItems.DeleteNode(SelNode);
  6839.             frmExplore.RootNode := Explorer.Selected; // update view
  6840.           end
  6841.           else
  6842.             Explorer.Selected.Delete;
  6843.         end;
  6844.  
  6845.         Status('Delete completed');
  6846.       finally
  6847.         if Assigned(frmConnect) then FreeProgressDialog;
  6848.       end;
  6849.     end;
  6850.   end;
  6851. end;
  6852.  
  6853. procedure TForm1.GetContactRestrict;
  6854. var
  6855.   sl: TStringList;
  6856.   function FindIdx(Substr: string): integer;
  6857.   var
  6858.     i: integer;
  6859.   begin
  6860.     Result := -1;
  6861.     for i := 0 to sl.Count-1 do
  6862.       if Pos(Substr,sl[i]) <> 0 then begin
  6863.         Result := i;
  6864.         break;
  6865.       end;
  6866.   end;
  6867.   function FindStr(Substr: string): string;
  6868.   var
  6869.     i: integer;
  6870.   begin
  6871.     i := FindIdx(Substr);
  6872.     if i = -1 then Result := ''
  6873.       else Result := sl[i];
  6874.   end;
  6875.   function GetMaxME(DefVal: cardinal): cardinal;
  6876.   var
  6877.     s: string;
  6878.   begin
  6879.     try
  6880.       s := FindStr('Maximum-Records');
  6881.       if s <> '' then begin
  6882.         Delete(s,1,16);
  6883.         if s <> '*' then begin
  6884.           Result := StrToInt(s);
  6885.           exit;
  6886.         end;
  6887.       end;
  6888.       Result := 0;
  6889.       s := FindStr('Total-Records');
  6890.       if s <> '' then begin
  6891.         Delete(s,1,14);
  6892.         Result := Result + cardinal(StrToInt(s));
  6893.       end;
  6894.       s := FindStr('Free-Records');
  6895.       if s <> '' then begin
  6896.         Delete(s,1,13);
  6897.         Result := Result + cardinal(StrToInt(s));
  6898.       end;
  6899.     except
  6900.       Result := DefVal;
  6901.     end;
  6902.   end;
  6903.   function GetMaxLen(Field: string; DefVal: cardinal): cardinal;
  6904.   var
  6905.     s: string;
  6906.     i: integer;
  6907.   begin
  6908.     Result := DefVal;
  6909.     try
  6910.       s := FindStr(Field);
  6911.       if s <> '' then begin
  6912.         i := Pos(':=',s);
  6913.         Delete(s,1,i+1);
  6914.         Result := StrToInt(s);
  6915.       end;
  6916.     except
  6917.       Result := DefVal;
  6918.     end;
  6919.   end;
  6920. begin
  6921.   if not FStartupOptions.NoObex and FUseObex then begin
  6922.     sl := TStringList.Create;
  6923.     try
  6924.       try
  6925.         ObexGetObject('telecom/pb/info.log',sl);
  6926.         { T610 example:
  6927.         Total-Records:149
  6928.         Maximum-Records:*
  6929.         Free-Records:346
  6930.         DID:6D25
  6931.         IEL:0x08
  6932.         HD:YES
  6933.         SAT:CC
  6934.         MCL:NO
  6935.         ICL:NO
  6936.         OCL:NO
  6937.         X-IRMC-FIELDS:
  6938.         <Begin>
  6939.         VERSION:
  6940.         N;CHARSET=ISO-8859-1;CHARSET=UTF-7[1=15;2=15]:=30
  6941.         EMAIL;TYPE=INTERNET:=50
  6942.         TITLE;CHARSET=ISO-8859-1;CHARSET=UTF-7:=15
  6943.         ORG;CHARSET=ISO-8859-1;CHARSET=UTF-7:=15
  6944.         X-TEL-TYPES:6
  6945.         TEL;TYPE=WORK:=40
  6946.         TEL;TYPE=HOME:=40
  6947.         TEL;TYPE=CELL:=40
  6948.         TEL;TYPE=FAX:=40
  6949.         TEL:=40
  6950.         X-IRMC-LUID:=12
  6951.         REV:
  6952.         <End>
  6953.         }
  6954.       finally
  6955.         FlushOK;
  6956.       end;  
  6957.       with frmSyncPhonebook do begin
  6958.         // Set phonebook ME size
  6959.         FMaxRecME := GetMaxME(510);
  6960.         Debug('Contact: Set max items = '+IntToStr(FMaxRecME));
  6961.         // Set contact fields max size
  6962.         FMaxNameLen := GetMaxLen('N;',30);
  6963.         Debug('Contact: Set name length = '+IntToStr(FMaxNameLen));
  6964.         FMaxMailLen := GetMaxLen('EMAIL;',50);
  6965.         Debug('Contact: Set e-mail length = '+IntToStr(FMaxMailLen));
  6966.         FMaxTitleLen := GetMaxLen('TITLE',15);
  6967.         Debug('Contact: Set title length = '+IntToStr(FMaxTitleLen));
  6968.         FMaxOrgLen := GetMaxLen('ORG;',15);
  6969.         Debug('Contact: Set organization length = '+IntToStr(FMaxOrgLen));
  6970.         { TODO: should we check individual numbers here? (work,cell...) }
  6971.         FMaxTellen := GetMaxLen('TEL:',40);
  6972.         Debug('Contact: Set phone length = '+IntToStr(FMaxTellen));
  6973.         // Set Obex LUID size
  6974.         FMaxLuidLen := GetMaxLen('X-IRMC-LUID:',FMaxLuidLen);
  6975.         Debug('Contact: Set LUID length = '+IntToStr(FMaxLuidLen));
  6976.       end;
  6977.     finally
  6978.       sl.Free;
  6979.     end;
  6980.   end;
  6981. end;
  6982.  
  6983. procedure TForm1.ObexListFolder(Path: WideString; var Dir: TStringList; Connect: boolean);
  6984. var
  6985.   StringStream: TStringStream;
  6986.   i: integer;
  6987. begin
  6988.  StringStream := TStringStream.Create('');
  6989.  Dir.Clear();
  6990.  
  6991.  if Connect then
  6992.   ObexConnect(ObexFolderBrowserServiceID);
  6993.  
  6994.  try
  6995.   //Debug('Obex folder accessing '+Path);
  6996.  
  6997.   if (Path = '') or (Path[1] <> '/') then                      // make sure we always go
  6998.    Path := '/' + Path;                                         //    to the root dir
  6999.  
  7000.   while (Length(Path) > 1) and (Path[Length(Path)] = '/') do   // trunc last '/'
  7001.    Delete(Path, Length(Path), 1);                              // otherwise we'd end up in the root
  7002.  
  7003.   {
  7004.   s := HTMLEncode(Path);
  7005.   if s <> Path then begin
  7006.     Debug('HTML: Encoding '+Path+' to '+s);
  7007.     Path := s;
  7008.   end;
  7009.   }
  7010.  
  7011.   Path := '"' + StringReplace(Path, '/', '"/"', [rfReplaceAll]) + '"';   // to make sure CL-LF's and spaces aren't seen as new item
  7012.  
  7013.   // changing nested dirs at once (Pictures/Camera) doesn't seem to be supported
  7014.   // so we do it in steps (change to '/' -> change to 'Pictures' -> change to 'Camera')
  7015.  
  7016.   with TStringList.Create() do
  7017.   try
  7018.    Delimiter := '/';
  7019.    DelimitedText := Path;
  7020.  
  7021.    for i := 0 to Count - 1 do
  7022.     FObex.ChangeDir(Strings[i]);
  7023.  
  7024.   finally
  7025.    Free();
  7026.   end;
  7027.  
  7028.   FObex.List(StringStream);            // get current dir contents
  7029.   Dir.LoadFromStream(StringStream);
  7030.  finally
  7031.   StringStream.Free();
  7032.  
  7033.   if Connect then                      // don't forget to disconnect
  7034.    ObexDisconnect();                   // if we connected ourselves
  7035.  end;
  7036. end;
  7037.  
  7038. procedure TForm1.InitObexFolders;
  7039. var
  7040.   XML: TXML;
  7041.   XMLNode: TXMLNode;
  7042.   h: string;
  7043.   fname: WideString;
  7044.   Dir,Files: TStringList;
  7045.   Node: TTntTreeNode;
  7046. begin
  7047.   if FStartupOptions.NoObex or not FUseObex then exit;
  7048.   {
  7049.   <?xml version="1.0" encoding="UTF-8"?>
  7050.   <!DOCTYPE folder-listing SYSTEM "obex-folder-listing.dtd">
  7051.   <!--
  7052.   Generated by XML Coder.
  7053.   xml_coder.c (Sep 24 2003 11:24:33)
  7054.   (C) 2001 Sony Ericsson Mobile Communications AB, Lund, Sweden
  7055.   -->
  7056.   <folder-listing version="1.0"><folder name="My Picture"/>
  7057.   <folder name="My Sounds"/>
  7058.   <folder name="My Themes"/>
  7059.   </folder-listing>
  7060.   }
  7061.   if not CoolTrayIcon1.CycleIcons then
  7062.     Status('Loading folders...');
  7063.   ObexConnect(ObexFolderBrowserServiceID);
  7064.   Dir := TStringList.Create;
  7065.   Files := TStringList.Create;
  7066.   try
  7067.     FNodeObex.DeleteChildren;
  7068.     Explorer.Update;
  7069.     try
  7070.       ObexListFolder('',Dir,False);
  7071.     except
  7072.       on e: Exception do begin
  7073.         Status('Obex Folder Browsing not supported: '+e.Message);
  7074.         if FConnectionType = 1 then // IR Connection
  7075.           ActivityLog('Obex Folder Browsing: This feature is currently not supported when using IR connection.');
  7076.         exit;
  7077.       end;
  7078.     end;
  7079.  
  7080.     XML := TXML.Create();
  7081.     try
  7082.      XML.XML := Dir.Text;
  7083.  
  7084.      XMLNode := XML.FirstChild;
  7085.      while assigned(XMLNode) do
  7086.      begin
  7087.       if XMLNode.TagName = 'folder' then
  7088.       begin
  7089.        fName := XMLNode.attribute['name'];
  7090.        h := HTMLDecode(fname);
  7091.        if h <> fname then begin
  7092.         Debug('HTML: Decoding ' + fname + ' to ' + h);
  7093.         fname := h;
  7094.        end;
  7095.  
  7096.        if FUseUTF8 then fname := UTF8Decode(fname);
  7097.        Node := Explorer.Items.AddChild(FNodeObex,fname);
  7098.        Node.ImageIndex := 33;
  7099.        Node.StateIndex := 0;
  7100.        try
  7101.         ObexListFolder(fname,Files,False);
  7102.         PharseObexDir(Node,Files);
  7103.        except
  7104.         Node.Delete;
  7105.         raise;
  7106.        end;
  7107.       end;
  7108.  
  7109.       XMLNode := XMLNode.NextSibling;
  7110.      end;
  7111.     finally
  7112.  
  7113.      XML.Free();
  7114.     end;
  7115.     FNodeObex.Expand(False);
  7116.     if not CoolTrayIcon1.CycleIcons then
  7117.       Status('');
  7118.   finally
  7119.     Dir.Free;
  7120.     Files.Free;
  7121.     ObexDisconnect;
  7122.     if frmExplore.Visible then frmExplore.RootNode := Explorer.Selected;
  7123.   end;
  7124. end;
  7125.  
  7126. procedure TForm1.PharseObexDir(Node: TtntTreeNode; Dir: TStringList);
  7127.   { T610 example: -----------------------------------------------
  7128.   <?xml version="1.0" encoding="UTF-8"?>
  7129.   <!DOCTYPE folder-listing SYSTEM "obex-folder-listing.dtd">
  7130.   <!--
  7131.   Generated by XML Coder.
  7132.   xml_coder.c (Sep 24 2003 11:24:33)
  7133.   (C) 2001 Sony Ericsson Mobile Communications AB, Lund, Sweden
  7134.   -->
  7135.   <folder-listing version="1.0"><parent-folder/>
  7136.   <file name="006.jpg" size="4802"/>
  7137.   <file name="BI4A44~1.jpg" size="6250"/>
  7138.   <file name="Rose.wbmp" size="134"/>
  7139.   </folder-listing>
  7140.   }
  7141.  
  7142.   { K700i example: ----------------------------------------------
  7143.   <?xml version="1.0" encoding="UTF-8"?>
  7144.   <!DOCTYPE folder-listing SYSTEM "obex-folder-listing.dtd">
  7145.   <!--
  7146.   Generated by XML Coder.
  7147.   .\cxc125821_EU_1_C\IAR-ARM7\src\xml_coder.c (May 29 2004 00:04:41)
  7148.   ⌐ 2001 Sony Ericsson Mobile Communications AB, Lund, Sweden
  7149.   -->
  7150.   <folder-listing version="1.0"><parent-folder/>
  7151.   <file name="HBK_2.gif" size="2094"/>
  7152.   <file name="PB002.gif" size="5955"/>
  7153.   <file name="Winter.gif" size="14331"/>
  7154.   <folder name="camera_semc"/>              <===== sub-folder !!
  7155.   </folder-listing>
  7156.   }
  7157.  
  7158.  function FixString(InString: string): string;
  7159.  begin
  7160.   result := HTMLDecode(InString);
  7161.  
  7162.   if result <> InString then
  7163.     Debug('HTML: Decoding ' + InString + ' to ' + result);
  7164.  
  7165.   if fUseUTF8 then
  7166.    result := UTF8Decode(result);
  7167.  end;
  7168.  
  7169. var
  7170.   CurName: WideString;
  7171.   CurSize: string;
  7172.   SubNode: TtntTreeNode;
  7173.   XML: TXML;
  7174.   XMLNode: TXMLNode;
  7175.   SL: TStringList;
  7176. begin
  7177.  Node.DeleteChildren();
  7178.  Explorer.Update();
  7179.  
  7180.  XML := TXML.Create();
  7181.  try
  7182.   XML.XML := Dir.Text;
  7183.  
  7184.   // first check for dirs, they should appear first in the list
  7185.   XMLNode := XML.FirstChild;
  7186.   while assigned(XMLNode) do
  7187.   begin
  7188.    if SameText(XMLNode.TagName, 'folder') then
  7189.    begin
  7190.     CurName := FixString(XMLNode.attribute['name']);
  7191.  
  7192.     SL := TStringList.Create();
  7193.     try
  7194.      SubNode := Explorer.Items.AddChild(Node, CurName);
  7195.      SubNode.ImageIndex := Node.ImageIndex;
  7196.      SubNode.StateIndex := 0;
  7197.  
  7198.      try
  7199.       ObexListFolder(ObexFolderPath(SubNode), SL, false);
  7200.       PharseObexDir(SubNode, SL);
  7201.      except
  7202.       SubNode.Delete();
  7203.       { TODO: Handle dir list failure here! }
  7204.      end;
  7205.     finally
  7206.      SL.Free();
  7207.     end;
  7208.    end;
  7209.  
  7210.    XMLNode := XMLNode.NextSibling;
  7211.   end;
  7212.  
  7213.   // now check for files in this dir
  7214.   XMLNode := XML.FirstChild;
  7215.   while assigned(XMLNode) do
  7216.   begin
  7217.    if SameText(XMLNode.TagName, 'file') then
  7218.    begin
  7219.     CurName := FixString(XMLNode.attribute['name']);
  7220.     CurSize := XMLNode.attribute['size'];
  7221.  
  7222.     if SameText(RightStr(CurSize, 1), 'D') then                   // check for '12345d' case
  7223.      SetLength(CurSize, Length(CurSize) - 1);                     // cut of 'd' if found
  7224.  
  7225.     with Explorer.Items.AddChild(Node, CurName) do
  7226.     begin
  7227.      StateIndex := StrToIntDef(CurSize, 0);                       // fail safe default (0)
  7228.      ImageIndex := ExplorerFindExtImage(ExtractFileExt(CurName)); // get file imageindex ased on file ext
  7229.  
  7230.      case ImageIndex of
  7231.       38,
  7232.       36: Node.ImageIndex := 34;
  7233.       37: Node.ImageIndex := 35;
  7234.      else
  7235.       ImageIndex := 27;
  7236.      end;
  7237.     end;
  7238.    end;
  7239.  
  7240.    XMLNode := XMLNode.NextSibling;
  7241.   end;
  7242.  finally
  7243.   XML.Free();
  7244.  end;
  7245. end;
  7246.  
  7247. procedure TForm1.ObexPutFile(filename: WideString; Delete,Silent: boolean);
  7248. begin
  7249.   RequestConnection;
  7250.   { We don't call ObexConnect here since we don't know in
  7251.     which server the file should go. So, the phone will
  7252.     handle file put request and it will do whatsoever. }
  7253.   try
  7254.     if Delete then begin
  7255.       ObexConnect(ObexFolderBrowserServiceID);
  7256.       try
  7257.         FObex.PutFile(filename,True); // delete
  7258.         if not Silent then
  7259.           ShowBaloonInfo('File "'+ExtractFileName(filename)+'" deleted.')
  7260.       finally
  7261.         ObexDisconnect;
  7262.       end
  7263.     end  
  7264.     else begin
  7265.       FObex.PutFile(filename);
  7266.       if not Silent then
  7267.         ShowBaloonInfo('File "'+ExtractFileName(filename)+'" sent to phone.');
  7268.     end;
  7269.   finally
  7270.     FlushOK;
  7271.   end;
  7272. end;
  7273.  
  7274. procedure TForm1.ActionToolsDownloadExecute(Sender: TObject);
  7275.  
  7276.  function ExtractDir(Node: TTntTreeNode): string;
  7277.  var
  7278.    ImageIndex: TImageIndex;
  7279.  begin
  7280.   Node := Node.Parent; // start at parent of 'file node'
  7281.   Imageindex := Node.ImageIndex;
  7282.  
  7283.   while assigned(Node) and (Node.ImageIndex = ImageIndex) do
  7284.   begin
  7285.    result := Node.Text + '/' + result;
  7286.    Node := Node.Parent;
  7287.   end;
  7288.  
  7289.   if (Length(Result) > 1) and (Result[Length(Result)] = '/') then
  7290.    SetLength(Result, Length(Result) - 1);
  7291.  end;
  7292.  
  7293. var
  7294.   fname,dname: WideString;
  7295.   Item: PExploreItem;
  7296.   Node: PVirtualNode;
  7297.   frmConnect: TfrmConnect;
  7298.   Multiselect: boolean;
  7299. begin
  7300.   { Multiple files selected? }
  7301.   Multiselect := frmExplore.Visible and frmExplore.ListItems.Focused and (frmExplore.ListItems.SelectedCount > 1);
  7302.  
  7303.   frmConnect := nil;
  7304.   try
  7305.     if frmExplore.Visible and frmExplore.ListItems.Focused and
  7306.       (frmExplore.ListItems.FocusedNode <> nil) then begin
  7307.       Item := frmExplore.ListItems.GetNodeData(frmExplore.ListItems.FocusedNode);
  7308.       fname := Item.name;
  7309.       dname := Explorer.Selected.Text;  // <-- still ok ? how about sub-dirs ?
  7310.     end
  7311.     else begin
  7312.       fname := Explorer.Selected.Text;
  7313. //      dname := Explorer.Selected.Parent.Text;
  7314.       dName := ExtractDir(Explorer.Selected);
  7315.     end;
  7316.     ObexSaveDialog.FileName := fname;
  7317.     ObexSaveDialog.Filter := 'Similar Files|*'+ExtractFileExt(fname)+'|All Files|*.*';
  7318.     if ObexSaveDialog.Execute then begin
  7319.       if Multiselect then begin
  7320.         frmConnect := GetProgressDialog;
  7321.         if CanShowProgress then
  7322.           frmConnect.ShowProgress(FProgressLongOnly);
  7323.         frmConnect.SetDescr('Downloading files');
  7324.         Status('Downloading files');
  7325.         ObexGetFile(ObexSaveDialog.FileName,dname+'/'+fname);
  7326.         { Download rest of the files using same settings }
  7327.         Node := frmExplore.ListItems.GetFirst;
  7328.         while Node <> nil do begin
  7329.           if frmExplore.ListItems.Selected[Node] and (Node <> frmExplore.ListItems.FocusedNode) then begin
  7330.             frmConnect.SetDescr('Saving...');
  7331.             Item := frmExplore.ListItems.GetNodeData(Node);
  7332.             fname := Item.name;
  7333.             ObexSaveDialog.FileName := ExtractFilePath(ObexSaveDialog.FileName) + fname;
  7334.             if FileExists(ObexSaveDialog.FileName) then begin
  7335.               ObexSaveDialog.Filter := 'Similar Files|*'+ExtractFileExt(fname)+'|All Files|*.*';
  7336.               if not ObexSaveDialog.Execute then begin
  7337.                 Node := frmExplore.ListItems.GetNext(Node);
  7338.                 continue;
  7339.               end;
  7340.             end;
  7341.             ObexGetFile(ObexSaveDialog.FileName,dname+'/'+fname);
  7342.           end;
  7343.           Node := frmExplore.ListItems.GetNext(Node);
  7344.         end;
  7345.       end
  7346.       else
  7347.         { Download the selected file only }
  7348.         ObexGetFile(ObexSaveDialog.FileName,dname+'/'+fname);
  7349.     end;
  7350.  
  7351.     Status('Download completed');
  7352.   finally
  7353.     if Assigned(frmConnect) then FreeProgressDialog;
  7354.   end;
  7355. end;
  7356.  
  7357. procedure TForm1.ObexGetFile(filename,objname: WideString; Silent: boolean);
  7358. begin
  7359.   RequestConnection;
  7360.   ObexConnect(ObexFolderBrowserServiceID);
  7361.   try
  7362.     FObex.GetFile(filename,objname,Silent);
  7363.     if not Silent then
  7364.       ShowBaloonInfo('File "'+ExtractFileName(filename)+'" received from phone.');
  7365.   finally
  7366.     ObexDisconnect;
  7367.   end;
  7368. end;
  7369.  
  7370. function TForm1.LocatePBName(Where: string; Index: integer;
  7371.   var Number: string): string;
  7372. var
  7373.   slTmp: TStringList;
  7374.   Who: string;
  7375.   s: WideString;
  7376.   contact: PContactData;
  7377. begin
  7378.   // +CPBR: 100,"+359xxxxxxxxx",145,"Ilko"
  7379.   Result := '';
  7380.   TxAndWait('AT+CPBS="'+Where+'"');
  7381.   TxAndWait('AT+CPBR=' + IntToStr(Index));
  7382.   if Pos('+CPBR',FRxBuffer[0]) = 1 then begin
  7383.     slTmp := TStringList.Create;
  7384.     try
  7385.       s := FRxBuffer.Strings[0];
  7386.       if FUseUTF8 then s := UTF8Decode(s);
  7387.       slTmp.DelimitedText := s;
  7388.       Number := slTmp.Strings[2];
  7389.       if (slTmp.Strings[3] = '145') and (Number[1] <> '+') then
  7390.         Number := '+' + Number;
  7391.       Who := slTmp.Strings[4];
  7392.       if (Length(Who) > 2) and (Who[Length(Who)-1] = '/') then
  7393.         Who := Copy(Who,1,Length(Who)-2);
  7394.       { Do cache phone number position }
  7395.       if frmSyncPhonebook.FindContact(Who,contact) then
  7396.         SetContactPosition(contact,slTmp.Strings[2],Index);
  7397.       Result := Who;
  7398.     finally
  7399.       slTmp.Free;
  7400.     end;
  7401.   end;
  7402. end;
  7403.  
  7404.  
  7405. function TForm1.LocatePBName(Where: string; Index: integer): string;
  7406. var
  7407.   dummy: string;
  7408. begin
  7409.   Result := LocatePBName(Where,Index,dummy);
  7410. end;
  7411.  
  7412. function TForm1.LocatePBIndex(Where: string; Person: WideString; Phone: string): integer;
  7413. var
  7414.   Tm,i,Pos: Integer;
  7415.   slTmp: TStrings;
  7416.   Num: string;
  7417.   Who,s: WideString;
  7418.   contact: PContactData;
  7419.   sl: TStringList;
  7420. begin
  7421.   // +CPBF: 13,"35988xxxxxxx",145,"Ilko/H"
  7422.   // +CPBF: 100,"359887xxxxxxx",145,"Ilko/M"
  7423.   Result := -1;
  7424.   if FUseUTF8 then s := UTF8Encode(Person) else s := Person;
  7425.   Debug('Searching for contact info: '+Person);
  7426.   TxAndWait('AT+CPBS="'+Where+'"');
  7427.   { Temporary increase timeout since searching may take alot of time }
  7428.   Tm := FInactivityTimeout;
  7429.   if Tm < 20000 then FInactivityTimeout := 20000;
  7430.   try
  7431.     TxAndWait('AT+CPBF="'+s+'"');
  7432.   finally
  7433.     FInactivityTimeout := Tm;
  7434.   end;
  7435.   sl := TStringList.Create;
  7436.   try
  7437.     sl.AddStrings(FRxBuffer);
  7438.     for i := 0 to sl.Count - 1 do begin
  7439.       if System.Pos('+CPBF', sl[i]) = 1 then begin
  7440.         slTmp := TStringList.Create;
  7441.         try
  7442.           s := sl[i];
  7443.           if FUseUTF8 then s := UTF8Decode(s);
  7444.           slTmp.DelimitedText := s;
  7445.  
  7446.           Pos := StrToInt(slTmp.Strings[1]);
  7447.           Num := slTmp.Strings[2];
  7448.           Who := slTmp.Strings[4];
  7449.           if (Length(Who) > 2) and (Who[Length(Who)-1] = '/') then
  7450.             Who := Copy(Who,1,Length(Who)-2);
  7451.   
  7452.           if (slTmp.Strings[3] = '145') and (Num[1] <> '+') then Num := '+' + Num;
  7453.         finally
  7454.           slTmp.Free;
  7455.         end;
  7456.         if (AnsiCompareText(Num,Phone) = 0) and (WideCompareText(Who,Person) = 0) then begin
  7457.           { Do cache phone number position }
  7458.           if frmSyncPhonebook.FindContact(Who,contact) then begin
  7459.             SetContactPosition(contact,Num,Pos);
  7460.             UpdateMEPhonebook;
  7461.           end;
  7462.           Result := Pos;
  7463.           break;
  7464.         end;
  7465.       end;
  7466.     end;
  7467.   finally
  7468.     sl.Free;
  7469.   end;
  7470. end;
  7471.  
  7472. procedure TForm1.SpeedButton1Click(Sender: TObject);
  7473. begin
  7474.   ActionConnectionExplorer.Execute;
  7475. end;
  7476.  
  7477. procedure TForm1.ActionConnectionExplorerUpdate(Sender: TObject);
  7478. begin
  7479.   ActionConnectionExplorer.Checked := PanelExplorer.Visible;
  7480.   DescrPanel.Visible := not PanelExplorer.Visible;
  7481.   DescrPanel.Update;
  7482. end;
  7483.  
  7484. procedure TForm1.ActionConnectionExplorerExecute(Sender: TObject);
  7485. begin
  7486.   ActionConnectionExplorer.Checked := not ActionConnectionExplorer.Checked;
  7487.   PanelExplorer.Visible := ActionConnectionExplorer.Checked;
  7488.   if DescrPanel.Visible then DescrPanel.Top := 0; // make on top
  7489.   Splitter1.Visible := PanelExplorer.Visible;
  7490.   Splitter1.Left := PanelExplorer.Left + PanelExplorer.Width;
  7491.   if frmInfoView.Visible then frmInfoView.OnResize(nil); 
  7492. end;
  7493.  
  7494. procedure TForm1.CalculateTimeLeft(Model,Charge: string; Position, Max: integer);
  7495. var
  7496.   pos,sec,secfix,PrevPos: integer;
  7497.   key,s,PrevCharge: string;
  7498.   PrevTime: TDateTime;
  7499.   Reg: TRegistry;
  7500.   days: integer;
  7501.   procedure SaveInfo;
  7502.   begin
  7503.     with Reg do begin
  7504.       WriteInteger('Power',Position);
  7505.       WriteString('Charge',Charge);
  7506.       WriteTime('When',Now);
  7507.     end;  
  7508.   end;
  7509. begin
  7510.   Reg := TRegistry.Create;
  7511.   with Reg do
  7512.   try
  7513.     PrevPos := -1;
  7514.     PrevCharge := Charge;
  7515.     PrevTime := Now;
  7516.     key := 'software\float\fma\'+Model;
  7517.     RootKey := HKEY_CURRENT_USER;
  7518.     if OpenKey(key,True) then
  7519.       try
  7520.         if ValueExists('Power') then PrevPos := ReadInteger('Power');
  7521.         if ValueExists('Charge') then PrevCharge := ReadString('Charge');
  7522.         if ValueExists('When') then PrevTime := ReadTime('When');
  7523.         if Charge = '' then Charge := PrevCharge;
  7524.         { is there are status change detected }
  7525.         if (PrevPos <> -1) or (PrevCharge <> Charge) then
  7526.           begin
  7527.             if PrevCharge = Charge then begin
  7528.               secfix := 0;
  7529.               sec := Round((Now - PrevTime) * SecsPerDay);
  7530.               pos := Abs(PrevPos-Position);
  7531.               (*
  7532.               { on every 30 secs or on status change calculate time left }
  7533.               if (sec mod 30 = 0) and (pos = 0) then begin
  7534.                 pos := 1;
  7535.                 { metter tune up: appr. +5 days on full batteries (4320*100) }
  7536.                 if (Position > 94) and not FOnACPower then
  7537.                   secfix := (4320 * (Position-94)) div (Max-94);
  7538.               end;
  7539.               *)
  7540.               if (pos = 0) and (Position > 94) and not FOnACPower then
  7541.                 secfix := (4320 * (Position-94)) div (Max-94);
  7542.               if (sec >= 10) and (pos > 0) then begin
  7543.                 //if PrevPos <> Position then SaveInfo;
  7544.                 inc(sec,secfix);  
  7545.                 { on AC power show time until charge complete }
  7546.                 if FOnACPower then begin
  7547.                   sec := Round((sec*(Max-Position))/pos);
  7548.                   frmInfoView.Label8.Caption := 'Estimated Charge Left:';
  7549.                 end
  7550.                 else begin
  7551.                   sec := Round((sec*Position)/pos);
  7552.                   frmInfoView.Label8.Caption := 'Estimated Time Left:';
  7553.                 end;
  7554.                 { show time left }
  7555.                 if sec = 0 then
  7556.                   if FOnACPower then frmInfoView.lblTimeLeft.Caption := 'done'
  7557.                   else frmInfoView.lblTimeLeft.Caption := 'none'
  7558.                 else begin
  7559.                   days := sec div SecsPerDay;
  7560.                   if days > 6 then days := 6;
  7561.                   s := 'day';
  7562.                   if days <> 1 then s := s + 's';
  7563.                   frmInfoView.lblTimeLeft.Caption := Format('%d %s, %.2d h %.2d m',
  7564.                     [days,s,(sec mod SecsPerDay) div 3600,(sec mod 3600) div 60]);
  7565.                 end;
  7566.               end
  7567.             end
  7568.             else begin
  7569.               SaveInfo;
  7570.               frmInfoView.lblTimeLeft.Caption := '?';
  7571.               frmInfoView.Label8.Caption := 'Estimated Time Left:';
  7572.             end;
  7573.           end
  7574.         else
  7575.           SaveInfo;
  7576.       finally
  7577.         CloseKey;
  7578.       end;
  7579.   finally
  7580.     Free;
  7581.   end;
  7582. end;
  7583.  
  7584. procedure TForm1.SyncPhoneClock1Click(Sender: TObject);
  7585. var
  7586.   s,LYear,LHour,LZone: string;
  7587.   TimeZone: TTimeZoneInformation;
  7588. begin
  7589.   RequestConnection;
  7590.   try
  7591.     //TxAndWait('AT+CCLK=?'); // sould this be here?
  7592.     TxAndWait('AT+CCLK?');
  7593.     { If connecting just check, dont sync }
  7594.     if not CoolTrayIcon1.CycleIcons and FDoSyncClock and (FClockSync <> 2) and
  7595.       ((FClockSync = 0) or (MessageDlg('Phone clock is not synchronized with PC clock. '+
  7596.       'Do you wish to update it now?',mtConfirmation,[mbYes,mbNo],0) = ID_YES)) then
  7597.       begin
  7598.         frmSyncPhonebook.SyncLog('Sync Phone Clock started.');
  7599.         LYear := FormatDateTime('yy"/"mm"/"dd',Date);
  7600.         LHour := FormatDateTime('hh":"nn":"ss',Time);
  7601.         if FLastClockTZ <> '' then
  7602.           if GetTimeZoneInformation(TimeZone) > TIME_ZONE_ID_UNKNOWN then begin
  7603.             LZone := Format('%.2d',[TimeZone.Bias div 15]);
  7604.             if LZone[1] = '-' then LZone[1] := '+'
  7605.               else if LZone <> '00' then LZone := '-'+LZone
  7606.                    else LZone := '+'+LZone;
  7607.           end
  7608.           else
  7609.             LZone := FLastClockTZ 
  7610.         else
  7611.           LZone := ''; // phone doesn't report time zone, so don't set it
  7612.         s := '"'+LYear+','+LHour+LZone+'"';
  7613.         try
  7614.           TxAndWait('AT+CCLK='+s);
  7615.           Debug('CLOCK: Updated!');
  7616.           FDoSyncClock := False;
  7617.           ShowBaloonInfo('Phone clock synchronized successfully.');
  7618.           frmSyncPhonebook.SyncLog('Sync Phone Clock completed');
  7619.         except
  7620.           CoolTrayIcon1.ShowBalloonHint(Application.Title,'Phone clock synchronization failed!',bitError,10);
  7621.           frmSyncPhonebook.SyncLog('Sync Phone Clock aborted');
  7622.           raise;
  7623.         end;
  7624.       end;
  7625.   except
  7626.     Debug('[ERROR] Sync Phone Clock failed!');
  7627.   end;
  7628. end;
  7629.  
  7630. procedure TForm1.ActionExplorerUpFolderUpdate(Sender: TObject);
  7631. begin
  7632.   ActionExplorerUpFolder.Enabled := Explorer.Selected <> Explorer.Items.GetFirstNode;
  7633. end;
  7634.  
  7635. procedure TForm1.ActionExplorerUpFolderExecute(Sender: TObject);
  7636. begin
  7637.   Explorer.Selected := Explorer.Selected.Parent;
  7638. end;
  7639.  
  7640. procedure TForm1.trayMenuPopup(Sender: TObject);
  7641. begin
  7642.   { Workaround for Win+D and Win+M keys }
  7643.   if IsIconic(Application.Handle) then
  7644.     ShowRestore1.Action := ActionWindowRestore
  7645.   else
  7646.     ShowRestore1.Action := ActionWindowMinimize;
  7647. end;
  7648.  
  7649. function TForm1.LookupNumber(Contact: String): String;
  7650. var
  7651.   Data: PContactData;
  7652. begin
  7653.   Result := '';
  7654.   if frmSyncPhonebook.FindContact(Contact,Data) then
  7655.     Result := GetContactDefPhone(Data);
  7656. end;
  7657.  
  7658. procedure TForm1.CoolTrayIcon1DblClick(Sender: TObject);
  7659. begin
  7660.   trayMenuPopup(trayMenu);
  7661.   ShowRestore1.Click;
  7662. end;
  7663.  
  7664. procedure TForm1.ActionBusyUpdate(Sender: TObject);
  7665. begin
  7666.   with (Sender as TAction) do begin
  7667.     { Do not put FConnected check here! }
  7668.     Enabled := not FBusy and not FObex.Connected and not FObexConnecting;
  7669.   end;
  7670. end;
  7671.  
  7672. procedure TForm1.ActionEditCommonUpdate(Sender: TObject);
  7673. begin
  7674.   with (Sender as TAction) do begin
  7675.     Enabled := frmMsgView.Visible or frmSyncPhonebook.Visible or frmSIMEdit.Visible or frmEditor.Visible or
  7676.       (frmExplore.Visible and (Explorer.Selected.Parent = FNodeGroups) and (frmExplore.ListItems.SelectedCount = 1)) or
  7677.       (frmExplore.Visible and (Explorer.Selected = FNodeGroups) and (frmExplore.ListItems.SelectedCount = 1)) or
  7678.       (frmExplore.Visible and (Explorer.Selected = FNodeBookmarks) and (frmExplore.ListItems.SelectedCount = 1)) or
  7679.       (frmExplore.Visible and (Explorer.Selected.Parent = FNodeObex) and (frmExplore.ListItems.SelectedCount <> 0));
  7680.   end;
  7681. end;
  7682.  
  7683. procedure TForm1.ActionContactsNewPersonUpdate(Sender: TObject);
  7684. begin
  7685.   ActionContactsNewPerson.Enabled := frmSyncPhonebook.Visible or frmSIMEdit.Visible;
  7686. end;
  7687.  
  7688. procedure TForm1.ActionContactsNewPersonExecute(Sender: TObject);
  7689. begin
  7690.   if frmSyncPhonebook.Visible then frmSyncPhonebook.btnNEWClick(nil);
  7691.   if frmSIMEdit.Visible then frmSIMEdit.NewPerson1Click(nil);
  7692. end;
  7693.  
  7694. procedure TForm1.ActionContactsVoiceCallUpdate(Sender: TObject);
  7695. begin
  7696.   ActionContactsVoiceCall.Enabled := not FObex.Connected;
  7697. end;
  7698.  
  7699. procedure TForm1.ActionContactsNewMsgUpdate(Sender: TObject);
  7700. begin
  7701.   ActionContactsNewMsg.Enabled := IsContactNumberSelected and (LocateSelContactNumber <> sUnknownNumber);
  7702. end;
  7703.  
  7704. function TForm1.LocateSelContactNumber: string;
  7705. var
  7706.   Number: String;
  7707.   contact: PContactData;
  7708.   simrec: PSimData;
  7709.   smsrec: PListData;
  7710.   Item: PExploreItem;
  7711. begin
  7712.   Number := '';
  7713.   try
  7714.     if frmInfoView.Visible and (ActiveControl is TTntListView) then begin
  7715.       Number := (Form1.ActiveControl as TTntListView).Selected.Caption;
  7716.     end
  7717.     else
  7718.     if frmSyncPhonebook.Visible and (ActiveControl = frmSyncPhonebook.ListContacts) then begin
  7719.       contact := frmSyncPhonebook.ListContacts.GetNodeData(frmSyncPhonebook.ListContacts.FocusedNode);
  7720.       if contact <> nil then
  7721.         Number := ContactNumberByName(GetContactFullName(contact));
  7722.     end
  7723.     else
  7724.     if frmMsgView.Visible and (ActiveControl = frmMsgView.ListMsg) then begin
  7725.       smsrec := frmMsgView.ListMsg.GetNodeData(frmMsgView.ListMsg.FocusedNode);
  7726.       if smsrec <> nil then
  7727.         Number := smsrec.from;
  7728.     end
  7729.     else
  7730.     if frmSIMEdit.Visible and (ActiveControl = frmSIMEdit.ListNumbers) then begin
  7731.       simrec := frmSIMEdit.ListNumbers.GetNodeData(frmSIMEdit.ListNumbers.FocusedNode);
  7732.       if simrec <> nil then
  7733.         Number := simrec.cname + ' [' + simrec.pnumb + ']';
  7734.     end
  7735.     else
  7736.     if frmExplore.Visible and (ActiveControl = frmExplore.ListItems) then begin
  7737.       Item := frmExplore.ListItems.GetNodeData(frmExplore.ListItems.FocusedNode);
  7738.       if Item <> nil then
  7739.         if frmExplore.ListItems.FocusedNode.Dummy = 8 then begin // contact
  7740.           Number := ContactNumberByName(Item.name);
  7741.         end
  7742.         else begin // calls
  7743.           Number := Item.name;
  7744.         end;
  7745.     end
  7746.     else
  7747.       if Explorer.Selected.ImageIndex = 8 then begin // explorer contact
  7748.         Number := ContactNumberByName(Explorer.Selected.Text);
  7749.       end
  7750.       else // explorer number (leaf, has contact as parent)
  7751.         Number := Explorer.Selected.Parent.Text + ' [' + Explorer.Selected.Text + ']';
  7752.   except
  7753.     Debug('Error: Could not found selected contact (if any)');
  7754.   end;  
  7755.   Result := Number;
  7756. end;
  7757.  
  7758. function TForm1.IsContactNumberSelected: boolean;
  7759. begin
  7760.   if ActiveControl = Explorer then
  7761.     Result := (Explorer.Selected <> nil) and (Explorer.Selected.ImageIndex in [8..13])
  7762.   else
  7763.   if frmInfoView.Visible and (ActiveControl is TTntListView) then
  7764.     Result := (ActiveControl as TTntListView).Selected <> nil
  7765.   else
  7766.   if ActiveControl = frmSyncPhonebook.ListContacts then
  7767.     Result := frmSyncPhonebook.ListContacts.SelectedCount = 1
  7768.   else
  7769.   if ActiveControl = frmExplore.ListItems then
  7770.     Result := (frmExplore.ListItems.FocusedNode <> nil) and (frmExplore.ListItems.FocusedNode.Dummy in [8,53,54,55])
  7771.   else
  7772.   if ActiveControl = frmSIMEdit.ListNumbers then
  7773.     Result := frmSIMEdit.ListNumbers.SelectedCount = 1
  7774.   else
  7775.   if ActiveControl = frmMsgView.ListMsg then
  7776.     Result := frmMsgView.ListMsg.SelectedCount = 1
  7777.   else
  7778.     Result := False;
  7779. end;
  7780.  
  7781. procedure TForm1.ActionSMSUpdate(Sender: TObject);
  7782. begin
  7783.   (Sender as TAction).Enabled := frmMsgView.Visible and (frmMsgView.ListMsg.SelectedCount <> 0);
  7784. end;
  7785.  
  7786. procedure TForm1.ActionContactsExportMEUpdate(Sender: TObject);
  7787. begin
  7788.   (Sender as TAction).Enabled := frmSyncPhonebook.Visible and (frmSyncPhonebook.ListContacts.SelectedCount <> 0);
  7789. end;
  7790.  
  7791. procedure TForm1.ExplorerAddToGroup(GroupIndex: integer;
  7792.   Contact: WideString);
  7793. var
  7794.   grp,cnt,num: TTntTreeNode;
  7795. begin
  7796.   grp := FNodeGroups.getFirstChild;
  7797.   while grp <> nil do
  7798.   try
  7799.     if grp.StateIndex = GroupIndex then begin
  7800.       cnt := grp.getFirstChild;
  7801.       while cnt <> nil do
  7802.       try
  7803.         { check if name already exists }
  7804.         if WideCompareText(cnt.Text,Contact) = 0 then begin
  7805.           num := cnt.getFirstChild;
  7806.           while num <> nil do
  7807.           try
  7808.             //TODO: check whether number is already added, if so exit.
  7809.           finally
  7810.             num := cnt.GetNextChild(num);
  7811.           end;
  7812.           exit; // exit anyway! remove when TODO completed
  7813.         end;
  7814.       finally
  7815.         cnt := grp.GetNextChild(cnt);
  7816.       end;
  7817.       with Explorer.Items.AddChild(grp,Contact) do begin
  7818.         ImageIndex := 8;
  7819.         StateIndex := grp.Count;
  7820.       end;
  7821.       break;
  7822.     end;
  7823.   finally
  7824.     grp := FNodeGroups.GetNextChild(grp);
  7825.   end;
  7826. end;
  7827.  
  7828. procedure TForm1.ExplorerContextPopup(Sender: TObject; MousePos: TPoint;
  7829.   var Handled: Boolean);
  7830. var
  7831.   Node: TTntTreeNode;
  7832. begin
  7833.   Node := Explorer.GetNodeAt(MousePos.X,MousePos.Y);
  7834.   if (Node <> nil) and (Node <> Explorer.Selected) then begin
  7835.     Explorer.Selected := Node;
  7836.     Application.ProcessMessages;
  7837.   end;
  7838. end;
  7839.  
  7840. procedure TForm1.ActionEditGoUpUpdate(Sender: TObject);
  7841. begin
  7842.   ActionEditGoUp.Enabled := (Explorer.Selected <> nil) and (Explorer.Selected.getPrevSibling <> nil);
  7843. end;
  7844.  
  7845. procedure TForm1.ActionEditGoUpExecute(Sender: TObject);
  7846. begin
  7847.   Explorer.Selected := Explorer.Selected.getPrevSibling;
  7848. end;
  7849.  
  7850. procedure TForm1.ActionEditGoDownUpdate(Sender: TObject);
  7851. begin
  7852.   ActionEditGoDown.Enabled := (Explorer.Selected <> nil) and (Explorer.Selected.getNextSibling <> nil);
  7853. end;
  7854.  
  7855. procedure TForm1.ActionEditGoDownExecute(Sender: TObject);
  7856. begin
  7857.   Explorer.Selected := Explorer.Selected.getNextSibling;
  7858. end;
  7859.  
  7860. procedure TForm1.ActionSMSArchiveMsgUpdate(Sender: TObject);
  7861. begin
  7862.   (Sender as TAction).Enabled := (Explorer.Selected <> nil) and
  7863.     (Explorer.Selected.ImageIndex in [39,40]) and frmMsgView.Visible and
  7864.     (frmMsgView.ListMsg.SelectedCount <> 0);
  7865. end;
  7866.  
  7867. procedure TForm1.ActionConnectionDownloadUpdate(Sender: TObject);
  7868. var
  7869.   d: dword;
  7870. begin
  7871.   if not FBusy and not FObex.Connected and (Explorer.Selected <> nil) then begin
  7872.     d := (Explorer.Selected.StateIndex and $F00000) shr 20;
  7873.     ActionConnectionDownload.Enabled := (d in [1,2,3,4,5,7,8]) and ((d <> 2) or
  7874.       ((Explorer.Selected.StateIndex and $0C0000) = 0)); // remove Archive, Outbox and Drafts
  7875.   end
  7876.   else
  7877.     ActionConnectionDownload.Enabled := False;
  7878. end;
  7879.  
  7880. procedure TForm1.Properties1Click(Sender: TObject);
  7881. begin
  7882.   ShowExplorerProperties(Explorer.Selected);
  7883. end;
  7884.  
  7885. function TForm1.IsAutoConnect: boolean;
  7886. begin
  7887.   Result := ActionConnectionMonitor.Checked and (ActionConnectionMonitor.Tag = 1);
  7888. end;
  7889.  
  7890. procedure TForm1.DoProximityAway;
  7891. var
  7892.   i: integer;
  7893.   Ini: TInifile;
  7894.   ScreenSaverFile: string;
  7895.   function GetLongFileName(const FileName: string): string;
  7896.   var
  7897.     aInfo: TSHFileInfo;
  7898.   begin
  7899.     if SHGetFileInfo(PChar(FileName), 0, aInfo, SizeOf(aInfo), SHGFI_DISPLAYNAME) <> 0 then
  7900.       Result := StrPas(aInfo.szDisplayName)
  7901.     else
  7902.       Result := FileName;
  7903.   end;
  7904. begin
  7905.   if FProximityActive then exit;
  7906.   FProximityActive := True;
  7907.  
  7908.   Debug('Proximity detection: Away');
  7909.   PlaySound(pChar('FMA_Away'), 0, SND_ASYNC or SND_APPLICATION or SND_NODEFAULT);
  7910.  
  7911.   FLastVolume := GetVolume;
  7912.   with FProximityOptions do begin
  7913.     if RunSS then begin
  7914.       Ini := TInifile.Create('system.ini');
  7915.       try
  7916.         ScreenSaverFile := GetLongFileName(Ini.Readstring('boot', 'SCRNSAVE.EXE', ''));
  7917.         if ScreenSaverFile <> '' then begin
  7918.           ScreenSaverFile := ExpandFileName(ScreenSaverFile);
  7919.           ShellExecute(Handle,'open',PChar(ScreenSaverFile),'',
  7920.             PChar(ExtractFileDir(ScreenSaverFile)),SW_SHOWNORMAL);
  7921.         end;
  7922.       finally
  7923.         Ini.Free;
  7924.       end;
  7925.     end;  
  7926.     if AwayLock then
  7927.       ShellExecute(Handle,'open','Rundll32.exe','user32.dll,LockWorkStation','',SW_HIDE);
  7928.     case AwayMusicMode of
  7929.       0: begin // mute
  7930.            SetMute(True);
  7931.            FLastVolume := -1;
  7932.          end;
  7933.       1: begin // unmute
  7934.            SetMute(False);
  7935.            FLastVolume := -1;
  7936.          end;
  7937.       2: begin // decrease 80%
  7938.            for i := 10 downto 2 do begin
  7939.              SetVolume(Round(i*FLastVolume/10));
  7940.              WaitASec(100,True);
  7941.            end;
  7942.          end;
  7943.       3: begin // increase 80%
  7944.            for i := 2 to 10 do begin
  7945.              SetVolume(Round(i*FLastVolume/2));
  7946.              WaitASec(100,True);
  7947.            end;
  7948.          end;
  7949.     end;
  7950.   end;
  7951.   ScriptEvent('OnProximity', [1]);
  7952. end;
  7953.  
  7954. procedure TForm1.DoProximityNear;
  7955. var
  7956.   i: integer;
  7957. begin
  7958.   if not FProximityActive then exit;
  7959.   FProximityActive := False;
  7960.  
  7961.   Debug('Proximity detection: Near');
  7962.   PlaySound(pChar('FMA_Near'), 0, SND_ASYNC or SND_APPLICATION or SND_NODEFAULT);
  7963.  
  7964.   GetVolume;
  7965.   with FProximityOptions do begin
  7966.     if NearUnlock then
  7967.       { not supported yet } ;
  7968.     case NearMusicMode of
  7969.       0: SetMute(True);  // mute
  7970.       1: SetMute(False); // unmute
  7971.       2: if FLastVolume <> -1 then begin // decrease 80%
  7972.            for i := 10 downto 2 do begin
  7973.              SetVolume(Round(i*FLastVolume/2));
  7974.              Sleep(100);
  7975.              Application.ProcessMessages;
  7976.            end;
  7977.          end;
  7978.       3: if FLastVolume <> -1 then begin // increase 80%
  7979.            for i := 2 to 10 do begin
  7980.              SetVolume(Round(i*FLastVolume/10));
  7981.              Sleep(100);
  7982.              Application.ProcessMessages;
  7983.            end;
  7984.          end;
  7985.     end;
  7986.   end;
  7987.   ScriptEvent('OnProximity', [0]);
  7988. end;
  7989.  
  7990. function TForm1.GetMute: Boolean;
  7991. begin
  7992.   AudioMixer1.GetMute (0,-1, MD);
  7993.   AudioMixer1.GetVolume (0,-1,L,R,M,Stereo,VD,MD,MS);
  7994.  
  7995.   Result := M<>0;
  7996. end;
  7997.  
  7998. function TForm1.GetVolume: Integer;
  7999. begin
  8000.   AudioMixer1.GetMute (0,-1, MD);
  8001.   AudioMixer1.GetVolume (0,-1,L,R,M,Stereo,VD,MD,MS);
  8002.  
  8003.   Result := Round(((L+R)/2)/65536 * 100);
  8004. end;
  8005.  
  8006. procedure TForm1.SetMute(Mute: Boolean);
  8007. begin
  8008.   AudioMixer1.SetVolume (0,-1,L,-1,byte(Mute)); // left = right
  8009. end;
  8010.  
  8011. procedure TForm1.SetVolume(Percentage: Integer);
  8012. begin
  8013.   if Percentage < 0 then Percentage := 0;
  8014.   if Percentage > 100 then Percentage := 100;
  8015.   AudioMixer1.SetVolume (0,-1,Round(Percentage/100*65536),-1,-1); // left = right, ignore mute
  8016. end;
  8017.  
  8018. procedure TForm1.PopupMenu1Popup(Sender: TObject);
  8019. begin
  8020.   if Explorer.Selected <> nil then begin
  8021.     { TODO: update $310000 with node variable }
  8022.     notenew1.Visible := Explorer.Selected.StateIndex = $310000;
  8023.     bookmarknew1.Visible := Explorer.Selected = FNodeBookmarks;
  8024.     NewGroup1.Visible := Explorer.Selected = FNodeGroups;
  8025.     EditProfile1.Visible := (Explorer.Selected.ImageIndex = 24) and
  8026.       (WideCompareText(Explorer.Selected.Text,cbProfile.Text) = 0);
  8027.     ActionToolsChangeProfile.Update;
  8028.     ActivateProfile1.Visible := ActivateProfile1.Enabled;
  8029.     EditWapHomePage2.Visible := bookmarknew1.Visible {and EditWapHomePage2.Enabled};
  8030.   end
  8031.   else begin
  8032.     notenew1.Visible := False;
  8033.     bookmarknew1.Visible := False;
  8034.     EditProfile1.Visible := False;
  8035.     ActivateProfile1.Visible := False;
  8036.     EditWapHomePage2.Visible := False;
  8037.   end;
  8038. end;
  8039.  
  8040. procedure TForm1.DownloadAllMessages;
  8041. var
  8042.   sl: TStrings;
  8043.   frmConnect: TfrmConnect;
  8044. begin
  8045.   RequestConnection;
  8046.   Status('Start Sync Messages...');
  8047.   frmConnect := GetProgressDialog;
  8048.   try
  8049.     if CanShowProgress then
  8050.       frmConnect.ShowProgress(FProgressLongOnly);
  8051.     sl := FNodeMsgInbox.Data;
  8052.     sl.Clear;
  8053.     { get all (4) messages: DownloadSMS(4,sl); }
  8054.     frmConnect.SetDescr('Downloading read messages');
  8055.     Debug('Startup: Downloading read messages');
  8056.     DownloadSMS(1,sl);
  8057.     frmConnect.SetDescr('Downloading unread messages');
  8058.     Debug('Startup: Downloading unread messages');
  8059.     DownloadSMS(0,sl);
  8060.     sl := FNodeMsgSent.Data;
  8061.     sl.Clear;
  8062.     frmConnect.SetDescr('Downloading sent messages');
  8063.     Debug('Startup: Downloading sent messages');
  8064.     DownloadSMS(3,sl);
  8065.     frmConnect.SetDescr('Saving messages data');
  8066.     Debug('Startup: Saving messages data');
  8067.     if frmMsgView.Visible then begin
  8068.       sl := Explorer.Selected.Data;
  8069.       frmMsgView.RenderListView(sl);
  8070.     end;
  8071.     { Update database }
  8072.     SaveData;
  8073.   finally
  8074.     FreeProgressDialog;
  8075.   end;
  8076.   Status('Sync Messages completed');
  8077. end;
  8078.  
  8079. procedure TForm1.DownloadSMS(msgType: Integer; memLocation: String;
  8080.   var sl: TStrings);
  8081. var
  8082.   i, memType: Integer;
  8083.   header, str: String;
  8084.   ml: TStringList;
  8085. begin
  8086.   if frmInfoView.Visible then EBCAState(False); // disable EBCA to avoid unsolicited msg
  8087.   if memLocation = 'ME' then memType := 1
  8088.   else memType := 2;
  8089.   try
  8090.     {
  8091.     <msgType> Description
  8092.     0 Received unread (new) message Default setting
  8093.     1 Received read message
  8094.     2 Stored unread message (only applicable to SMs)
  8095.     3 Stored sent message (only applicable to SMs)
  8096.     4 All messages
  8097.     16 Template message
  8098.     }
  8099.     TxAndWait('AT+CPMS="' + memLocation + '"');
  8100.     TxAndWait('AT+CMGL=' + IntToStr(msgType));
  8101.     ml := TStringList.Create;
  8102.     ml.AddStrings(FRxBuffer);
  8103.     try
  8104.       for i := 0 to ml.Count - 1 do begin
  8105.         if pos('+CMGL', ml[i]) = 1 then begin
  8106.           header := trim(copy(ml[i], 8, length(ml[i])));
  8107.           { TODO: 'header' already contains info if the message is 'new' }
  8108.           str := IntToStr(memType) + ',' + header + ',' + ml[i+1] + ',,0'; //0=not new
  8109.           sl.Add(str);
  8110.         end;
  8111.       end;
  8112.     finally
  8113.       ml.Free;
  8114.     end;
  8115.   except
  8116.     Status('Error downloading SMS');
  8117.   end;
  8118.   if frmInfoView.Visible then EBCAState(True);
  8119. end;
  8120.  
  8121. procedure TForm1.DownloadSMS(msgType: Integer; var sl: TStrings);
  8122. begin
  8123.   try
  8124.     DownloadSMS(msgType, 'SM', sl);
  8125.     DownloadSMS(msgType, 'ME', sl);
  8126.   except
  8127.     Status('Error Downloading SMS');
  8128.   end;
  8129. end;
  8130.  
  8131. procedure TForm1.ShowExplorer1Click(Sender: TObject);
  8132. begin
  8133.   ActionConnectionExplorer.Execute;
  8134. end;
  8135.  
  8136. function TForm1.LoadPhoneDataFiles(ID: string): boolean;
  8137. var
  8138.   Fullpath: string;
  8139.   UpgradeFromSingleDB: boolean;
  8140.   FDirID: TItemIDList;
  8141.   PDirID: PItemIDList;
  8142.   i: integer;
  8143. begin
  8144.   Result := True;
  8145.   if ID = '' then ID := PhoneIdentity;
  8146.   { First, save any localy changes, if needed }
  8147.   SaveData;
  8148.   { Now clear all views! }
  8149.   ClearExplorerViews;
  8150.   { New load new database... }
  8151.   Fullpath := ExePath;
  8152.   if ID <> '' then begin
  8153.     Fullpath := ExePath+'data\'+ID+'\dat\';
  8154.     { Should we upgrade from single database }
  8155.     UpgradeFromSingleDB := not DirectoryExists(Fullpath) and FileExists(ExePath + 'SMSInbox.dat');
  8156.     if UpgradeFromSingleDB and not FileExists(Fullpath + 'SMSInbox.dat') then
  8157.       if MessageDlg('Do you wish to migrate current database entries into a new database profile for this '+
  8158.         ID+' phone?'#13#13'If you are not sure or if the phone is connecting for the first time, click Yes.',
  8159.         mtConfirmation,[mbYes,mbNo],0) = mrYes then
  8160.         try
  8161.           { Create new profile database and migrate single db files }
  8162.           Status('Upgrading phone profile database...');
  8163.           Debug('Database: Upgrading from single database');
  8164.           ForceDirectories(Fullpath);
  8165.           CopyFile(PChar(string(ExePath) + 'SMSInbox.dat'),PChar(Fullpath + 'SMSInbox.dat'),True);
  8166.           CopyFile(PChar(string(ExePath) + 'SMSOutbox.dat'),PChar(Fullpath + 'SMSOutbox.dat'),True);
  8167.           CopyFile(PChar(string(ExePath) + 'SMSSent.dat'),PChar(Fullpath + 'SMSSent.dat'),True);
  8168.           CopyFile(PChar(string(ExePath) + 'SMSArchive.dat'),PChar(Fullpath + 'SMSArchive.dat'),True);
  8169.           CopyFile(PChar(string(ExePath) + 'SMSDrafts.dat'),PChar(Fullpath + 'SMSDrafts.dat'),True);
  8170.           CopyFile(PChar(string(ExePath) + 'Contacts.ME.dat'),PChar(Fullpath + 'Contacts.ME.dat'),True);
  8171.           CopyFile(PChar(string(ExePath) + 'Contacts.SM.dat'),PChar(Fullpath + 'Contacts.SM.dat'),True);
  8172.           CopyFile(PChar(string(ExePath) + 'Contacts.SYNC.dat'),PChar(Fullpath + 'Contacts.SYNC.dat'),True);
  8173.           CopyFile(PChar(string(ExePath) + 'Contacts.SYNCMAX.dat'),PChar(Fullpath + 'Contacts.SYNCMAX.dat'),True);
  8174.           CopyFile(PChar(string(ExePath) + 'Bookmarks.dat'),PChar(Fullpath + 'Bookmarks.dat'),True);
  8175.           CopyFile(PChar(string(ExePath) + 'Phone.dat'),PChar(Fullpath + 'Phone.dat'),True);
  8176.           Debug('Database: Upgrade completed');
  8177.         except
  8178.         end;
  8179.   end;
  8180.   { Loading data files }
  8181.   Status('Loading phone profile database...');
  8182.   Debug('Database: Load from '+Fullpath);
  8183.   LoadingDBFiles := True;
  8184.   try
  8185.     with TIniFile.Create(Fullpath + 'Phone.dat') do
  8186.       try
  8187.         FSelPhone := ReadString('Global','PhoneName','');
  8188.         FSMSCounterReseted := ReadBool('SMS','Reset',False);
  8189.         FSMSCounterResetDay := ReadInteger('SMS','Reset Day',1);
  8190.         FSMSCounter := ReadInteger('SMS','Count',0);
  8191.         FSMSWarning := ReadInteger('SMS','Warning',10);
  8192.         FOutlookCategories := ReadString('Outlook','Categories','');
  8193.         FSelectedOutlookFolders := ReadString('Outlook','ContactsFolder','DEFAULT');
  8194.         FOutlookNewContactsFolder := ReadString('Outlook','NewContactsFolder','');
  8195.         FBookmarkRootFolder := ReadString('Bookmarks','Root','');
  8196.         if FBookmarkRootFolder = '' then begin
  8197.           { Get default Favories folder }
  8198.           SetLength(FBookmarkRootFolder,MAX_PATH);
  8199.           PDirID := @FDirID;
  8200.           SHGetSpecialFolderLocation(Application.Handle,CSIDL_FAVORITES,PDirID);
  8201.           SHGetPathFromIDList(PDirID,@FBookmarkRootFolder[1]);
  8202.           FBookmarkRootFolder := StrPas(@FBookmarkRootFolder[1]);
  8203.         end;
  8204.         ReadSectionValues('Favorites SMS',FFavoriteRecipients);
  8205.         for i := 0 to FFavoriteRecipients.Count-1 do
  8206.           FFavoriteRecipients[i] := FFavoriteRecipients.Values[FFavoriteRecipients.Names[i]];
  8207.         ReadSectionValues('Favorites Call',FFavoriteCalls);
  8208.         for i := 0 to FFavoriteCalls.Count-1 do
  8209.           FFavoriteCalls[i] := FFavoriteCalls.Values[FFavoriteCalls.Names[i]];
  8210.       finally
  8211.         Free;
  8212.       end;
  8213.   except
  8214.     Result := False;
  8215.   end;
  8216.   try
  8217.     TStrings(FNodeMsgInbox.Data).Clear;
  8218.     TStrings(FNodeMsgInbox.Data).LoadFromFile(Fullpath + 'SMSInbox.dat');
  8219.     UpdateNewMessagesCounter(FNodeMsgInbox);
  8220.   except
  8221.     Result := False;
  8222.   end;
  8223.   try
  8224.     TStrings(FNodeMsgOutbox.Data).Clear;
  8225.     TStrings(FNodeMsgOutbox.Data).LoadFromFile(Fullpath + 'SMSOutbox.dat');
  8226.     UpdateNewMessagesCounter(FNodeMsgOutbox);
  8227.   except
  8228.     Result := False;
  8229.   end;
  8230.   try
  8231.     TStrings(FNodeMsgSent.Data).Clear;
  8232.     TStrings(FNodeMsgSent.Data).LoadFromFile(Fullpath + 'SMSSent.dat');
  8233.   except
  8234.     Result := False;
  8235.   end;
  8236.   try
  8237.     TStrings(FNodeMsgArchive.Data).Clear;
  8238.     TStrings(FNodeMsgArchive.Data).LoadFromFile(Fullpath + 'SMSArchive.dat');
  8239.     UpdateNewMessagesCounter(FNodeMsgArchive);
  8240.   except
  8241.     Result := False;
  8242.   end;
  8243.   try
  8244.     TStrings(FNodeMsgDrafts.Data).Clear;
  8245.     TStrings(FNodeMsgDrafts.Data).LoadFromFile(Fullpath + 'SMSDrafts.dat');
  8246.     UpdateNewMessagesCounter(FNodeMsgDrafts);
  8247.   except
  8248.     Result := False;
  8249.   end;
  8250.   try
  8251.     TStrings(FNodeContactsME.Data).Clear;
  8252.     TStrings(FNodeContactsME.Data).LoadFromFile(Fullpath + 'Contacts.ME.dat');
  8253.     RenderContactList(FNodeContactsME);
  8254.   except
  8255.     Result := False;
  8256.   end;
  8257.   try
  8258.     TStrings(FNodeContactsSM.Data).Clear;
  8259.     TStrings(FNodeContactsSM.Data).LoadFromFile(Fullpath + 'Contacts.SM.dat');
  8260.     RenderContactList(FNodeContactsSM);
  8261.     frmSIMEdit.RenderData(True);
  8262.   except
  8263.     Result := False;
  8264.   end;
  8265.   try
  8266.     TStrings(FNodeBookmarks.Data).Clear;
  8267.     TStrings(FNodeBookmarks.Data).LoadFromFile(Fullpath + 'Bookmarks.dat');
  8268.     RenderBookmarkList(FNodeBookmarks);
  8269.   except
  8270.     Result := False;
  8271.   end;
  8272.   try
  8273.     frmSyncPhonebook.LoadContacts(Fullpath + 'Contacts.SYNC.dat');
  8274.   except
  8275.     Result := False;
  8276.   end;
  8277.   { Database files loaded }
  8278.   LoadingDBFiles := False;
  8279.   FDatabaseLoaded := True;
  8280.   { Remember last open database }
  8281.   PhoneIdentity := ID;
  8282.   { Update view }
  8283.   if FSelPhone <> '' then
  8284.     Explorer.Items.GetFirstNode.Text := FSelPhone
  8285.   else
  8286.     Explorer.Items.GetFirstNode.Text := 'My Phone';
  8287.   ExplorerChange(Self,Explorer.Selected);  
  8288.   if not CoolTrayIcon1.CycleIcons then Status('') else Status('Connecting...');
  8289. end;
  8290.  
  8291. function TForm1.CanShowProgress: boolean;
  8292. begin
  8293.   Result := not FDontProgress and (not FProgressRestoredOnly or
  8294.     (FormStorage1.StoredValue['StartMinimized'] = False));
  8295. end;
  8296.  
  8297. function TForm1.ExplorerFindExtImage(Ext: string): integer;
  8298. begin
  8299.   if (Ext = '.thm') then begin
  8300.     Result := 27
  8301.   end else
  8302.   if (Ext = '.amr') then begin
  8303.     Result := 38;
  8304.   end else
  8305.   if (Ext = '.mid') or (Ext = '.imy') then begin
  8306.     Result := 36;
  8307.   end else
  8308.   if (Ext = '.gif') or (Ext = '.jpg') or (Ext = '.wbmp') then begin
  8309.     Result := 37;
  8310.   end else
  8311.     Result := -1;
  8312. end;
  8313.  
  8314. procedure TForm1.DoProximityTest;
  8315. var
  8316.   ps: TProximityOptions;
  8317.   time: cardinal;
  8318. begin
  8319.   Debug('Testing proximity detection...');
  8320.   ps := FProximityOptions;
  8321.   with FProximityOptions,frmOptions do begin
  8322.     AwayLock := cbProximityLock.Checked;
  8323.     AwayMusicMode := rgProximityAway.ItemIndex;
  8324.     NearUnlock := cbProximityUnlock.Checked;
  8325.     NearMusicMode := rgProximityNear.ItemIndex;
  8326.   end;
  8327.   try
  8328.     DoProximityAway;
  8329.     try
  8330.       Debug('Proximity detection: Sleeping 5 seconds...');
  8331.       time := GetTickCount + 5000; // wait 5 seconds
  8332.       while GetTickCount < time do begin
  8333.         Application.ProcessMessages;
  8334.         Sleep(50);
  8335.       end;
  8336.     finally
  8337.       DoProximityNear;
  8338.     end;
  8339.   finally
  8340.     FProximityOptions := ps;
  8341.   end;
  8342. end;
  8343.  
  8344. procedure TForm1.DoDisconnectTemporary;
  8345. begin
  8346.   FTemporaryOffline := True;
  8347.   { remember re-connect state }
  8348.   FLastReconnect := ActionConnectionMonitor.Checked;
  8349.   ActionConnectionDisconnect.Execute;
  8350.   WaitASec(10);
  8351.   { allow auto re-connect }
  8352.   ActionConnectionMonitor.Checked := True;
  8353.   ActionConnectionMonitor.Tag := 1;
  8354. end;
  8355.  
  8356. procedure TForm1.RequestConnection(DoNotRefreshView: boolean);
  8357. begin
  8358.   FDoNotRefreshViewOnConnect := DoNotRefreshView;
  8359.   if not FConnected then ActionConnectionConnect.Execute;
  8360. end;
  8361.  
  8362. procedure TForm1.ActionViewMsgPreviewUpdate(Sender: TObject);
  8363. begin
  8364.   if (frmMsgView <> nil) and frmMsgView.Visible then begin
  8365.     ActionViewMsgPreview.Enabled := True;
  8366.     ActionViewMsgPreview.Checked := frmMsgView.PreviewPanel.Visible;
  8367.   end
  8368.   else
  8369.     ActionViewMsgPreview.Enabled := False;
  8370. end;
  8371.  
  8372. procedure TForm1.ActionViewMsgPreviewExecute(Sender: TObject);
  8373. begin
  8374.   ActionViewMsgPreview.Checked := not ActionViewMsgPreview.Checked;
  8375.   UpdateMessagePreview;
  8376. end;
  8377.  
  8378. procedure TForm1.UpdateMessagePreview;
  8379. begin
  8380.   frmMsgView.PreviewPanel.Visible := ActionViewMsgPreview.Checked;
  8381.   frmMsgView.Splitter2.Visible := ActionViewMsgPreview.Checked;
  8382.   if frmMsgView.Splitter2.Visible then
  8383.     frmMsgView.Splitter2.Top := frmMsgView.PreviewPanel.Top-1;
  8384.   if frmMsgView.Visible then frmMsgView.ListMsgChange(nil,nil);  
  8385. end;
  8386.  
  8387. procedure TForm1.InitCalls;
  8388. begin
  8389.   if Assigned(FNodeCalls) then
  8390.   try
  8391.     if frmInfoView.Visible then EBCAState(False);
  8392.     if not CoolTrayIcon1.CycleIcons then
  8393.       Status('Loading Calls...');
  8394.     InitCalls(fnodecallsIn);
  8395.     InitCalls(fnodecallsOut);
  8396.     InitCalls(fnodecallsMissed);
  8397.     if frmInfoView.Visible then EBCAState(True);
  8398.     FNodeCalls.Expand(False);
  8399.   except
  8400.     Debug('Error getting Calls');
  8401.   end;
  8402. end;
  8403.  
  8404. procedure TForm1.Timer2Timer(Sender: TObject);
  8405. const
  8406.   LastSendFailure: TDateTime = 0;
  8407.   UnsentCount: integer = 0;
  8408.   KeybCheck: integer = 0;
  8409.   TwoSecs: boolean = False;
  8410. var
  8411.   s: string;
  8412.   i: integer;
  8413.   IsLocked: boolean;
  8414. begin
  8415.   if not Timer1.Enabled then exit;
  8416.   Timer2.Enabled := False;
  8417.   Timer2.Interval := 1000;
  8418.   TwoSecs := not TwoSecs;
  8419.   if Application.Terminated then
  8420.     exit;
  8421.   try
  8422.     { On every second... }
  8423.     if (ActionMissedCalls <> nil) and (ActionMissedCalls.Enabled) then begin
  8424.       if ActionMissedCalls.ImageIndex = 16 then
  8425.         ActionMissedCalls.ImageIndex := 36
  8426.       else
  8427.         ActionMissedCalls.ImageIndex := 16;
  8428.     end;
  8429.     { On every 2 seconds... }
  8430.     if TwoSecs and Assigned(FObex) and not FObex.Connected and not FObexConnecting and not FBusy and
  8431.       ((frmCalling <> nil) and not frmCalling.IsCalling and not frmCalling.IsTalking) then begin
  8432.       if IsScriptInitialized and ActionConnectionAutoConnect.Checked and (ActionConnectionAutoConnect.Tag = 0) then begin
  8433.         { will wait until script is initialized before perform connect on startup }
  8434.         try
  8435.           RequestConnection;
  8436.         finally
  8437.           { Connect on startup succeeded or Aborted by user }
  8438.           ActionConnectionAutoConnect.Tag := byte(FConnected or FAbortDetected);
  8439.         end;  
  8440.       end
  8441.       else
  8442.       if not FConnected then begin
  8443.         if ActionConnectionMonitor.Checked and (ActionConnectionMonitor.Tag = 1) then
  8444.           ActionConnectionConnectExecute(nil);
  8445.       end
  8446.       else
  8447.       if FNewMessageList.Count > 0 then begin
  8448.         HandleNewSMS(FNewMessageList.Strings[0]);
  8449.         if FMsgM then FNewMessageList.Delete(0);
  8450.       end;
  8451.       { should be perform Outbox check now? }
  8452.       i := TStrings(FNodeMsgOutbox.Data).Count;
  8453.       if (i <> 0) and ((LastSendFailure = 0) or (((Now - LastSendFailure) * SecsPerDay) >= 30)) then begin
  8454.         { yes, are we work in offline mode? }
  8455.         if not FConnected then begin
  8456.           { yes, but if Connect on startup is active, wait for connection to be established... }
  8457.           if not ActionConnectionAutoConnect.Checked or (ActionConnectionAutoConnect.Tag <> 0) then
  8458.             { otherwise ask user to start connection in order to send outbox messages }
  8459.             if UnsentCount <> i then begin
  8460.               UnsentCount := i; // ask just once per new messages
  8461.               if FCheckOutbox then begin
  8462.                 if i = 1 then s := 'one unsent message' else s := IntToStr(i)+' unsent messages';
  8463.                 if MessageDlg('You have '+s+'. Do you wish to connect and process your Outbox now?',
  8464.                   mtConfirmation,[mbYes,mbNo],0) = ID_YES then
  8465.                   RequestConnection;
  8466.               end;
  8467.             end;
  8468.         end
  8469.         else
  8470.           { perform Outbox check in online mode :) }
  8471.           try
  8472.             // TODO: make DoProcessOutbox function to return success?
  8473.             DoProcessOutbox;
  8474.             if TStrings(FNodeMsgOutbox.Data).Count <> 0 then Abort
  8475.               else LastSendFailure := 0;
  8476.           except
  8477.             if LastSendFailure = 0 then
  8478.               Debug('Sending all Outbox messages failed. Will retry every 30 seconds...');
  8479.             LastSendFailure := Now;
  8480.           end;
  8481.       end;
  8482.       if FConnected and not FObexConnecting and not FObex.Connected and (ActiveThread = nil) then begin
  8483.         { Remove missed call/new message dialog box from phone }
  8484.         if FClearPhoneMessage then begin
  8485.           FClearPhoneMessage := False;
  8486.           { First unlock keyboard if needed }
  8487.           TxAndWait('AT+CLCK="CS",2');
  8488.           IsLocked := FKeybLocked;
  8489.           if IsLocked then
  8490.             ActionToolsKeybLock.Execute;
  8491.           { Remove popup }
  8492.           if IsT610Clone then
  8493.             try TxAndWait('AT+CKPD=":R"'); except end // T610
  8494.           else
  8495.             try TxAndWait('AT+CKPD="c"'); except end; // T68
  8496.           { Lock keyboard again if needed }
  8497.           if IsLocked then
  8498.             ActionToolsKeybLock.Execute;
  8499.         end;
  8500.         { Check keylock and proximity status }
  8501.         inc(KeybCheck);
  8502.         if FConnectingComplete and (KeybCheck = 3) then
  8503.           try // every 6 seconds
  8504.             KeybCheck := 0;
  8505.             { check keylock }
  8506.             TxAndWait('AT+CLCK="CS",2');
  8507.             { check silent }
  8508.             TxAndWait('AT*ESIL?');
  8509.             { TODO: Add HandleESIL() }
  8510.             for i := 0 to FRxBuffer.Count - 2 do
  8511.               if pos('*ESIL', FRxBuffer[i]) = 1 then begin
  8512.                 FSilentMode := Copy(FRxBuffer[i], 8, length(FRxBuffer[i])) = '1';
  8513.                 ActionToolsSilent.Enabled := True;
  8514.               end;
  8515.           except
  8516.             if FTimedout and not FAbortDetected then begin
  8517.               ScriptEvent('OnConnectionLost', []);
  8518.               Status('Connection: Lost!');
  8519.               if (frmCalling <> nil) and frmCalling.Visible then
  8520.                 frmCalling.Close;
  8521.             end;
  8522.           end;
  8523.       end;  
  8524.     end;
  8525.   finally
  8526.     if (frmInfoView <> nil) and frmInfoView.Visible then
  8527.       frmInfoView.UpdateWelcomePage;
  8528.     Timer2.Enabled := True;
  8529.   end;
  8530. end;
  8531.  
  8532. procedure TForm1.FmaOnTheWeb1Click(Sender: TObject);
  8533. begin
  8534.   ShellExecute(Handle,'open','http://fma.sourceforge.net/','','',SW_SHOWNORMAL);
  8535. end;
  8536.  
  8537. procedure TForm1.FmaOnSFNet1Click(Sender: TObject);
  8538. begin
  8539.   ShellExecute(Handle,'open','http://sourceforge.net/projects/fma','','',SW_SHOWNORMAL);
  8540. end;
  8541.  
  8542. procedure TForm1.FmaOnForums1Click(Sender: TObject);
  8543. begin
  8544.   ShellExecute(Handle,'open','http://fma.xinium.com/forums/','','',SW_SHOWNORMAL);
  8545. end;
  8546.  
  8547. procedure TForm1.ActionContactsAddContactUpdate(Sender: TObject);
  8548. begin
  8549.   ActionContactsAddContact.Enabled := IsContactNumberSelected and
  8550.     (LookupContact(LocateSelContactNumber) = '');
  8551. end;
  8552.  
  8553. procedure TForm1.ActionContactsAddContactExecute(Sender: TObject);
  8554. var
  8555.   contact: PContactData;
  8556.   Number: string;
  8557.   procedure UpdateView;
  8558.   begin
  8559.     if frmSyncPhonebook.Visible then
  8560.       frmSyncPhonebook.ListContacts.Repaint;
  8561.     if frmMsgView.Visible then
  8562.       frmMsgView.RenderListView(Explorer.Selected.Data);
  8563.     if frmInfoView.Visible then
  8564.       frmInfoView.UpdateWelcomePage(True);
  8565.   end;
  8566. begin
  8567.   Number := ExtractNumber(LocateSelContactNumber);
  8568.   with TfrmAddContact.Create(nil) do
  8569.     try
  8570.       NewNumber := Number;
  8571.       if ShowModal = mrOk then begin
  8572.         if RadioButton1.Checked then begin
  8573.           if frmSyncPhonebook.DoEdit(True,Number) then
  8574.             UpdateView;
  8575.         end;
  8576.         if RadioButton2.Checked then begin
  8577.           contact := GetSelectedContactData;
  8578.           case rgPhoneType.ItemIndex of
  8579.             0: contact^.cell := Number;
  8580.             1: contact^.work := Number;
  8581.             2: contact^.home := Number;
  8582.             3: contact^.fax := Number;
  8583.             4: contact^.other := Number;
  8584.           end;
  8585.           { Mark contact as Modified }
  8586.           contact^.StateIndex := 1;
  8587.           { Save changes }
  8588.           UpdateMEPhonebook;
  8589.           { Update fma views }
  8590.           UpdateView;
  8591.         end;
  8592.       end;
  8593.     finally
  8594.       Free;
  8595.     end;
  8596. end;
  8597.  
  8598. function TForm1.ExtractNumber(ContactNumber: WideString): WideString;
  8599. var
  8600.   i: integer;
  8601. begin
  8602.   i := Pos('[',ContactNumber);
  8603.   if i <> 0 then begin
  8604.     Delete(ContactNumber,1,i);
  8605.     i := Pos(']',ContactNumber);
  8606.     if i <> 0 then Delete(ContactNumber,i,Length(ContactNumber));
  8607.   end;
  8608.   Result := ContactNumber;
  8609. end;
  8610.  
  8611. procedure TForm1.ActionContactsOwnExecute(Sender: TObject);
  8612. var
  8613.   sl: TStringList;
  8614.   str: TMemoryStream;
  8615.   VCard: TVCard;
  8616.   cd: TContactData;
  8617.   contact: PContactData;
  8618. begin
  8619.   contact := @cd;
  8620.   sl := TStringList.Create;
  8621.   VCard := TVCard.Create;
  8622.   str := TMemoryStream.Create;
  8623.   try
  8624.     Status('Loading own card...');
  8625.     ObexConnect;
  8626.     try
  8627.       try
  8628.         ObexGetObject('telecom/pb/0.vcf',sl);
  8629.       except
  8630.         { Skip 'Not found' error }
  8631.         if FObex.LastErrorCode <> $C4 then raise;
  8632.       end;
  8633.     finally
  8634.       ObexDisconnect;
  8635.     end;
  8636.     Status('');
  8637.     { Edit card }
  8638.     VCard.Raw := sl;
  8639.     vCard2Contact(VCard,contact);
  8640.     contact^.stateindex := 3;
  8641.     if frmSyncPhonebook.DoEdit(False,'',contact) then begin
  8642.       Contact2vCard(contact,VCard);
  8643.       VCard.Raw.SaveToStream(str);
  8644.       str.Position := 0;
  8645.       Status('Saving own card...');
  8646.  
  8647.       raise Exception.Create('Not implemented yet');
  8648.       {
  8649.         Note: If MV, BC or HP is the currently selected phonebook storage, +CME
  8650.         ERROR: <err> will be returned.
  8651.         Note: DC, RC, and MC are not supported.
  8652.         Note: If phone is the currently selected phonebook storage, <text> will be
  8653.         interpreted as ölast nameö + "," + ôfirst nameö when stored in the
  8654.         hierarchical phonebook.
  8655.         Note: Flags may be used to indicate the contact field where the number
  8656.         should be stored. If no flag is used, the phone number will be stored as of
  8657.         type "home".
  8658.         Note: If phone is the currently selected phonebook storage and AT+CPBW
  8659.         is used with an <index> that is already used by another number, the old
  8660.         number will be overwritten and removed from whatever contact it was
  8661.         previously a part of.
  8662.       }
  8663.       TxAndWait('AT+CPBS="BC",password');
  8664.       if contact^.cell <> '' then
  8665.         TxAndWait('AT+CPBW=[<index>][,<number>[,<type>[,<text>]]]');
  8666.       {
  8667.       ObexConnect;
  8668.       try
  8669.         ObexPutObject('telecom/pb/0.vcf',str,False);
  8670.         Status('Own card modified');
  8671.       finally
  8672.         ObexDisconnect;
  8673.       end;
  8674.       }
  8675.     end;
  8676.   finally
  8677.     str.Free;
  8678.     sl.Free;
  8679.     VCard.Free;
  8680.   end;
  8681. end;
  8682.  
  8683. procedure TForm1.ExplorerCustomDrawItem(Sender: TCustomTreeView;
  8684.   Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
  8685. begin
  8686.   if ((Node.StateIndex and $F00000) = $200000) and ((Node.StateIndex and $0F0000) <> 0) then begin // SMS folders
  8687.     if Pos(' (',Node.Text) <> 0 then
  8688.       Explorer.Canvas.Font.Style := [fsBold]
  8689.     else
  8690.       Explorer.Canvas.Font.Style := [];
  8691.   end
  8692.   else
  8693.     Explorer.Canvas.Font.Style := [];
  8694. end;
  8695.  
  8696. procedure TForm1.ActionIsConnUpdate(Sender: TObject);
  8697. begin
  8698.   with (Sender as TAction) do begin
  8699.     Enabled := not FBusy and not FObex.Connected and FConnected;
  8700.   end;
  8701. end;
  8702.  
  8703. procedure TForm1.UpdateNewMessagesCounter(rootNode: TtntTreeNode; ModifyPDU: string; MarkAsRead: boolean);
  8704. var
  8705.   cnt,i,stat: integer;
  8706.   sl: TStrings;
  8707.   flag: string;
  8708.   s: WideString;
  8709. begin
  8710.   cnt := 0;
  8711.   sl := TStrings(rootNode.data);
  8712.   for i := 0 to sl.Count-1 do begin
  8713.     s := sl[i];
  8714.     { DB upgrade 0.10.29 build, where count is changed from 6 to 8 }
  8715.     if GetTokenCount(s) = 6 then
  8716.       s := s + ',';  // set date field as empty (unknown)
  8717.     if GetTokenCount(s) = 7 then begin
  8718.       s := s + ',';
  8719.       if MarkAsRead then s := s + '0' // clear new message flag
  8720.       else begin
  8721.         s := s + '1'; // set the new message flag
  8722.         inc(cnt);
  8723.       end;
  8724.       sl[i] := s;
  8725.       continue;
  8726.     end;
  8727.     try
  8728.       flag := GetToken(s,7);
  8729.       stat := StrToInt(flag);
  8730.       if stat <> byte(not MarkAsRead) then begin
  8731.         if ModifyPDU = GetToken(s,5) then begin // should we modify the item?
  8732.           s := Copy(s,1,Length(s)-Length(flag));
  8733.           if MarkAsRead then s := s + '0' // clear new message flag
  8734.           else begin
  8735.             s := s + '1'; // set the new message flag
  8736.             inc(cnt);
  8737.           end;
  8738.           sl[i] := s;
  8739.           continue;
  8740.         end;
  8741.       end;
  8742.       if stat <> 0 then inc(cnt);
  8743.     except
  8744.       on E: Exception do
  8745.         Debug('DB ERROR (' + E.Message + '): '+sl[i]);
  8746.     end;
  8747.   end;
  8748.   s := rootNode.Text;
  8749.   i := Pos(' (',s); // remove tail ' (num)' string
  8750.   if i <> 0 then rootNode.Text := Copy(s,1,i-1);
  8751.   if cnt <> 0 then rootNode.Text := rootNode.Text + ' (' + IntToStr(cnt) + ')';
  8752.   if rootNode = Explorer.Selected then lblCurrentPage.Caption := rootNode.Text;
  8753.   if frmInfoView.Visible then frmInfoView.UpdateWelcomePage;
  8754.   { TODO: Update Message view as well }
  8755. end;
  8756.  
  8757. function TForm1.FindObexFolderNode(AType: byte): TTntTreeNode; // 0-pics,1-snds
  8758. var
  8759.   Node: TTntTreeNode;
  8760. begin
  8761.   Result := nil;
  8762.   if Assigned(Form1.FNodeObex) then begin
  8763.     Node := Form1.FNodeObex.getFirstChild;
  8764.     while Node <> nil do
  8765.     try
  8766.       case AType of
  8767.         0: if Node.ImageIndex = 35 then begin // pic
  8768.           Result := Node;
  8769.           break;
  8770.         end;
  8771.         1: if Node.ImageIndex = 34 then begin // snd
  8772.           Result := Node;
  8773.           break;
  8774.         end;
  8775.         2: if Node.ImageIndex = 33 then begin // thm
  8776.           Result := Node;
  8777.           break;
  8778.         end;
  8779.       end;
  8780.     finally
  8781.       Node := Form1.FNodeObex.GetNextChild(Node);
  8782.     end;
  8783.   end;
  8784. end;
  8785.  
  8786. function TForm1.FindObexFolderName(AType: byte): WideString;
  8787. var
  8788.   Node: TTntTreeNode;
  8789. begin
  8790.   Node := FindObexFolderNode(AType);
  8791.   if Node <> nil then Result := Node.Text
  8792.     else Result := '';
  8793. end;
  8794.  
  8795. procedure TForm1.ShowExplorerProperties(Node: TTntTreeNode);
  8796. var
  8797.   contact: PContactData;
  8798.   sim: PSIMData;
  8799.   num: string;
  8800.   bt,bu: WideString;
  8801.   function ShowContactPropsME: boolean;
  8802.   begin
  8803.     Result := False;
  8804.     if frmSyncPhonebook.FindContact(Node.Text,contact) then
  8805.       with frmSyncPhonebook do begin
  8806.         SelContact := contact;
  8807.         Result := DoEdit;
  8808.       end;
  8809.   end;
  8810.   function ShowContactPropsSM: boolean;
  8811.   begin
  8812.     Result := False;
  8813.     if frmSIMEdit.FindContact(Node.Text,sim) then
  8814.       with frmSIMEdit do begin
  8815.         SelContact := sim;
  8816.         Result := DoEdit;
  8817.       end;
  8818.   end;
  8819. begin
  8820.   if (Node.ImageIndex = 24) and (Node.Text = cbProfile.Text) then begin
  8821.     { Edit current Profile instead showing common properties }
  8822.     ActionToolsEditProfile.Execute;
  8823.   end
  8824.   else
  8825.   if Node.ImageIndex = 8 then begin
  8826.     { Contact properties }
  8827.     if Node.Parent = FNodeContactsME then begin  // Phonebook
  8828.       ShowContactPropsME;
  8829.     end else
  8830.     if Node.Parent = FNodeContactsSM then begin  // SIM card
  8831.       ShowContactPropsSM;
  8832.     end else
  8833.     if Node.Parent.Parent = FNodeGroups then begin // Groups
  8834.       if FUseObex and not FStartupOptions.NoIRMC then ShowContactPropsME
  8835.       else ShowContactPropsSM;
  8836.     end;
  8837.   end
  8838.   else begin
  8839.     { Show common properties }
  8840.     with TfrmFolderProps.Create(nil) do
  8841.     try
  8842.       RootNode := Node;
  8843.       if ShowModal = mrOk then begin
  8844.         { Bookmark renamed? }
  8845.         if Notebook1.PageIndex = fpBookmark then begin
  8846.           num := IntToStr(BookmarkPhoneIndex);
  8847.           if num <> '1' then begin // bookmark at pos 1 is reserved
  8848.             RequestConnection;
  8849.             if FUseUTF8 then begin
  8850.               bu := UTF8Encode(BookmarkURL);
  8851.               bt := UTF8Encode(BookmarkTitle);
  8852.             end
  8853.             else begin
  8854.               bu := BookmarkURL;
  8855.               bt := BookmarkTitle;
  8856.             end;
  8857.             TxAndWait('AT*EWBA='+num+','); // delete old one
  8858.             TxAndWait('AT*EWBA=0,"'+bu+'","'+bt+'"');
  8859.             InitBookmarks;
  8860.           end;
  8861.         end;
  8862.         { Phone renamed? }
  8863.         if Notebook1.PageIndex = fpPhone then begin
  8864.           FSelPhone := TntEdit1.Text;
  8865.           Node.Text := FSelPhone;
  8866.           { Update view }
  8867.           ExplorerChange(nil,Explorer.Selected);
  8868.           { Update tray icon if phone is renamed }
  8869.           if FConnected then CoolTrayIcon1.Hint := 'Fma - Connected to '+FSelPhone;
  8870.           { Save changes }
  8871.           SaveData;
  8872.         end;
  8873.       end;
  8874.     finally
  8875.       Free;
  8876.     end;
  8877.   end;
  8878. end;
  8879.  
  8880. function TForm1.FindExplorerChildNode(Named: WideString): TTntTreeNode;
  8881. var
  8882.   Child: TTntTreeNode;
  8883. begin
  8884.   Child := nil;
  8885.   if Explorer.Selected <> nil then begin
  8886.     Child := Explorer.Selected.getFirstChild;
  8887.     while Child <> nil do begin
  8888.       if WideCompareText(Child.Text,Named) = 0 then
  8889.         break;
  8890.       Child := Form1.Explorer.Selected.GetNextChild(Child);
  8891.     end;
  8892.   end;
  8893.   Result := Child;
  8894. end;
  8895.  
  8896. procedure TForm1.ScriptInitialize;
  8897. begin
  8898.   FScriptRunning := False;
  8899.   FScriptErrorOccur := False;
  8900.   try
  8901.     { Dako: Recreate entire script control component in order
  8902.       to avoid memory leaks... maybe }
  8903.     ScriptControl.AutoObjects.Clear;
  8904.     ScriptControl.Free;
  8905.     FAccessoriesMenu := nil;
  8906.     ScriptControl := TawScriptControl.Create(Self);
  8907.     ScriptControl.OnCallFunction := ScriptControlCallFunction;
  8908.     ScriptControl.OnError := ScriptControlError;
  8909.     if not LoadScript then
  8910.       Abort;
  8911.     ScriptControl.AutoObjects.BeginUpdate;
  8912.     try
  8913.       FAccessoriesMenu := TAccessoriesMenu.Create;
  8914.       with ScriptControl.AutoObjects.Add do begin
  8915.         AutoObject := TMobileAgentApp.Create;  { TODO -oLordLarry : Memory Leak. AWScript is full of leaks }
  8916.         AutoObjectName := 'fma';
  8917.       end;
  8918.       with ScriptControl.AutoObjects.Add do begin
  8919.         AutoObject := FAccessoriesMenu;
  8920.         AutoObjectName := 'am';
  8921.       end;
  8922.     finally
  8923.       ScriptControl.AutoObjects.EndUpdate;
  8924.     end;
  8925.     ScriptEvent('OnInit', []);
  8926.     { Ok, script is loaded and initialized }
  8927.     FScriptInitialized := True;
  8928.   except
  8929.     ActivityLog('ERROR: Can not load script or create automation objects failed');
  8930.   end;  
  8931. end;
  8932.  
  8933. procedure TForm1.SaveMsgToFolder(var rootNode: TtntTreeNode; PDU: String; OverwriteOld,AsNew: boolean);
  8934. var
  8935.   buffer: String;
  8936.   sms: TSMS;
  8937.   EntryExist: Boolean;
  8938.   j: Integer;
  8939.   dt: TDateTime;
  8940.   sl: TStrings;
  8941. begin
  8942.   buffer := '3,' + IntToStr(TStrings(rootNode.Data).Count + 1) + ','; // index
  8943.  
  8944.   sms := TSMS.Create;
  8945.   try
  8946.     sms.PDU := PDU;
  8947.  
  8948.     if sms.IsOutgoing then buffer := buffer + '3,,,'
  8949.       else buffer := buffer + '1,,,';
  8950.  
  8951.     buffer := buffer + '"' + PDU + '",';
  8952.  
  8953.     dt := sms.TimeStamp;
  8954.     { if not timestamp is not set (i.e. outgoing sms) use current time }
  8955.     if dt = 0 then dt := Now;
  8956.     
  8957.     buffer := buffer + '"' + DateTimeToStr(dt) + '",' + IntToStr(Byte(AsNew));
  8958.   finally
  8959.     sms.Free;
  8960.   end;
  8961.  
  8962.   sl := TStrings(rootNode.Data);
  8963.   EntryExist := False;
  8964.   for j := 0 to sl.count-1 do begin
  8965.     if AnsiCompareText(GetToken(sl[j],5),PDU) = 0 then begin
  8966.       if OverwriteOld then begin
  8967.         { Mark message as new depending of AsNew }
  8968.         buffer := sl[j];
  8969.         { DB upgrade 0.10.29 build, where count is changed from 6 to 8 }
  8970.         if GetTokenCount(buffer) = 6 then
  8971.           buffer := buffer + '"' + DateTimeToStr(dt) + '",' + IntToStr(Byte(AsNew))
  8972.         else begin
  8973.           Delete(buffer,Length(buffer),1);
  8974.           buffer := buffer + IntToStr(Byte(AsNew));
  8975.         end;
  8976.         sl[j] := buffer;
  8977.       end;  
  8978.       EntryExist := True;
  8979.       break;
  8980.     end;
  8981.   end;
  8982.   if not EntryExist then
  8983.     sl.Add(buffer);
  8984.  
  8985.   UpdateNewMessagesCounter(rootNode);
  8986.   if (rootNode = Explorer.Selected) and frmMsgView.Visible then frmMsgView.RenderListView(sl);
  8987. end;
  8988.  
  8989. procedure TForm1.DoProcessOutbox;
  8990. const
  8991.   sem: boolean = false;
  8992. var
  8993.   i,j: integer;
  8994.   s,d: WideString;
  8995.   pdu,newpdu: string;
  8996.   sl: TStrings;
  8997.   sms: TSMS;
  8998.   OldMsec: cardinal;
  8999.   chat: TfrmCharMessage;
  9000. begin
  9001.   if sem then exit;
  9002.   sem := True;
  9003.   frmInfoView.linkSendMessages.Enabled := False;
  9004.   try
  9005.     RequestConnection;
  9006.     if frmInfoView.Visible then EBCAState(False);
  9007.     Status('Sending messages from Outbox...');
  9008.     TxAndWait('AT+CMGF=0'); // set PDU mode
  9009.     TxAndWait('AT+CSMS=0'); // check if phone supports SMS commands
  9010.     TxAndWait('AT+CPMS="ME","ME"'); // store messages in ME phonebook
  9011.     sl := TStrings(FNodeMsgOutbox.Data);
  9012.     i := 0;
  9013.     while sl.Count > i do begin
  9014.       pdu := GetToken(sl[i],5);
  9015.       try
  9016.         { Sending... }
  9017.         sms := TSMS.Create;
  9018.         try
  9019.           { Send message... }
  9020.           sms.PDU := pdu;
  9021.           chat := GetChatWindow(sms.Number);
  9022.           TxAndWait('AT+CMGS=' + IntToStr(sms.TPLength), '>'); // send message
  9023.           { Temporary increase timeout since sending may take alot of time }
  9024.           OldMsec := FInactivityTimeout;
  9025.           if OldMsec < 20000 then FInactivityTimeout := 20000;
  9026.           try
  9027.             try
  9028.               TxAndWait(pdu + #$1A);
  9029.             finally
  9030.               FInactivityTimeout := OldMsec;
  9031.             end;
  9032.           except
  9033.             { Message NOT sent, notify Chat }
  9034.             if Assigned(chat) then begin
  9035.               chat.Show;
  9036.               chat.BringToFront;
  9037.               chat.EnableSending(True);
  9038.             end;
  9039.             raise; // continue with exception
  9040.           end;
  9041.           try
  9042.             { Message sent OK, notify Chat }
  9043.             if Assigned(chat) then begin
  9044.               chat.Show;
  9045.               chat.BringToFront;
  9046.               chat.AddChatText('',sms.Text,Now);
  9047.             end;
  9048.             { Store it in Archive folder }
  9049.             try
  9050.               { Update TP Message Refference, with one reported by phone }
  9051.               newpdu := pdu;
  9052.               for j := 0 to FRxBuffer.Count-1 do
  9053.                 if Pos('+CMGS:',FRxBuffer[j]) = 1 then begin
  9054.                   { get message reference }
  9055.                   s := FRxBuffer[j];
  9056.                   Delete(s,1,7);
  9057.                   d := IntToHex(StrToInt(GetToken(s,0)),2);
  9058.                   { update if needed }
  9059.                   if sms.MessageReference <> d then begin
  9060.                     Debug('Message refference changed from ' + sms.MessageReference + ' to ' + d);
  9061.                     newpdu := sms.GetNewPDU(d);
  9062.                   end;  
  9063.                   break;
  9064.                 end;
  9065.               SaveMsgToFolder(FNodeMsgArchive,newpdu,True,False);
  9066.             except
  9067.               // Aghh! An error in gsm_sms unit implementation, use original PDU !
  9068.               SaveMsgToFolder(FNodeMsgArchive,pdu,True,False);
  9069.             end;
  9070.           finally  
  9071.             { Remove from Outbox }
  9072.             sl.Delete(i);
  9073.             UpdateNewMessagesCounter(FNodeMsgOutbox);
  9074.             if (Explorer.Selected = FNodeMsgOutbox) and frmMsgView.Visible then frmMsgView.RenderListView(sl);
  9075.             { Remove from Drafts (if any) }
  9076.             DelMsgFromFolder(FNodeMsgDrafts,pdu);
  9077.           end;
  9078.         finally
  9079.           sms.Free;
  9080.         end;
  9081.  
  9082.         { Notify user }
  9083.         PlaySound(pChar('FMA_SMSSent'), 0, SND_ASYNC or SND_APPLICATION or SND_NODEFAULT);
  9084.  
  9085.         { Update SMS counter }
  9086.         if FSMSDoReset then
  9087.           { TODO: Reset counter is the reset-day has been passed too }
  9088.           if FSMSCounterResetDay = StrToInt(FormatDateTime('d',Date)) then
  9089.             if not FSMSCounterReseted then begin
  9090.               FSMSCounter := 0;
  9091.               FSMSCounterReseted := True;
  9092.             end
  9093.           else
  9094.             FSMSCounterReseted := False;
  9095.         inc(FSMSCounter);
  9096.         if frmMessageContact.Visible then
  9097.           frmMessageContact.FormActivate(frmMessageContact);
  9098.         { Wait a while }
  9099.         WaitASec;
  9100.         if FAbortDetected then break;
  9101.       except
  9102.         { Skip failed message, and try with next ones }
  9103.         inc(i);
  9104.       end;
  9105.     end;
  9106.     if sl.Count <> 0 then begin
  9107.       CoolTrayIcon1.ShowBalloonHint(Application.Title,'Outbox send failed! Will try later...',bitError,10);
  9108.       Status('Outbox send failed!');
  9109.       frmInfoView.linkSendMessages.Enabled := True;
  9110.     end
  9111.     else begin
  9112.       ShowBaloonInfo('Messages sent and moved to Archive.');
  9113.       Status('Outbox send complete');
  9114.     end;
  9115.     if frmInfoView.Visible then EBCAState(True);
  9116.   finally
  9117.     sem := False;
  9118.   end;
  9119. end;
  9120.  
  9121. function TForm1.DelMsgFromFolder(var rootNode: TtntTreeNode; PDU: String): Boolean;
  9122. var
  9123.   j: integer;
  9124.   sl: TStrings;
  9125. begin
  9126.   Result := False;
  9127.  
  9128.   sl := TStrings(rootNode.Data);
  9129.   for j := 0 to sl.count-1 do begin
  9130.     if AnsiCompareText(GetToken(sl[j],5), PDU) = 0 then begin
  9131.       { If deleteing from Outbox, notify and enable Chat window }
  9132.       if rootNode = FNodeMsgOutbox then
  9133.         ChatNotifyDel(PDU);
  9134.       { Delete msg }  
  9135.       sl.Delete(j);
  9136.       Result := True;
  9137.       break;
  9138.     end;
  9139.   end;
  9140.  
  9141.   if Result then begin
  9142.     UpdateNewMessagesCounter(rootNode);
  9143.     if (rootNode = Explorer.Selected) and frmMsgView.Visible then frmMsgView.RenderListView(sl);
  9144.   end;
  9145. end;
  9146.  
  9147. procedure TForm1.ActionConnectionSendOutboxMsgsExecute(Sender: TObject);
  9148. begin
  9149.   DoProcessOutbox;
  9150. end;
  9151.  
  9152. procedure TForm1.ActionConnectionSendOutboxMsgsUpdate(Sender: TObject);
  9153. begin
  9154.   ActionConnectionSendOutboxMsgs.Enabled := not FBusy and not FObex.Connected and
  9155.     (TStrings(FNodeMsgOutbox.Data).Count <> 0);
  9156. end;
  9157.  
  9158. procedure TForm1.WM_ENDSESSION(var Msg: TMessage);
  9159. begin
  9160.   if Boolean(Msg.WParam) then begin
  9161.     FExitWindows := True;
  9162.     if FConnected then ActionConnectionDisconnect.Execute;
  9163.     ActionExit.Execute;
  9164.     { COM object cleanup workaround }
  9165.     ScriptControl.AutoObjects.Clear;
  9166.     ScriptControl.Free;
  9167.     FAccessoriesMenu := nil;
  9168.     ScriptControl := TawScriptControl.Create(Self);
  9169.     ScriptControl.OnCallFunction := ScriptControlCallFunction;
  9170.     ScriptControl.OnError := ScriptControlError;
  9171.     Application.Terminate;
  9172.   end;
  9173.   Msg.Result := 0;
  9174. end;
  9175.  
  9176. procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  9177. begin
  9178.   if FCheckOutbox and (FExit or not FMinimize) and not FExitWindows and
  9179.     ActionConnectionSendOutboxMsgs.Update and ActionConnectionSendOutboxMsgs.Enabled then begin
  9180.     FCheckOutbox := False; // do not show two identical questions on exit
  9181.     try
  9182.     case MessageDlg('You have some unsent messages in your Outbox folder. Do you want to send them now?',
  9183.       mtConfirmation,[mbYes,mbNo,mbCancel],0) of
  9184.       ID_YES: DoProcessOutbox;
  9185.       ID_CANCEL: CanClose := False;
  9186.     end;
  9187.     finally
  9188.       FCheckOutbox := True;
  9189.     end;
  9190.   end;
  9191.   FExiting := CanClose;
  9192.   if not FExiting then
  9193.     FExit := False; // Restore main menu exit flag
  9194. end;
  9195.  
  9196. procedure TForm1.ActionToolsKeybLockUpdate(Sender: TObject);
  9197. begin
  9198.   ActionToolsKeybLock.Checked := FKeybLocked;
  9199.   ActionToolsKeybLock.ImageIndex := 39 + byte(FKeybLocked);
  9200.   if FKeybLocked then ActionToolsKeybLock.Caption := 'Unlock &Keyboard'
  9201.     else ActionToolsKeybLock.Caption := 'Lock &Keyboard';
  9202.   if not FConnected or FObex.Connected or FObexConnecting then
  9203.     ActionToolsKeybLock.Enabled := False;
  9204. end;
  9205.  
  9206. procedure TForm1.ActionToolsKeybLockExecute(Sender: TObject);
  9207. begin
  9208.   TxAndWait('AT+CLCK="CS",'+IntToStr(byte(not FKeybLocked)));
  9209.   FKeybLocked := not FKeybLocked;
  9210. end;
  9211.  
  9212. procedure TForm1.Explore(Node: TTntTreeNode);
  9213. begin
  9214.   Explorer.Selected := Node;
  9215. end;
  9216.  
  9217. procedure TForm1.cbTerminalEnter(Sender: TObject);
  9218. begin
  9219.   Button3.Default := True;
  9220. end;
  9221.  
  9222. procedure TForm1.cbTerminalExit(Sender: TObject);
  9223. begin
  9224.   Button3.Default := False;
  9225. end;
  9226.  
  9227. procedure TForm1.ActionSMSImportUpdate(Sender: TObject);
  9228. begin
  9229.   (Sender as TAction).Enabled := frmMsgView.Visible;
  9230. end;
  9231.  
  9232. procedure TForm1.ActionSMSImportExecute(Sender: TObject);
  9233. begin
  9234.   frmMsgView.ImportTextMessages1.Click;
  9235. end;
  9236.  
  9237. procedure TForm1.ActionContactsImportMEUpdate(Sender: TObject);
  9238. begin
  9239.   (Sender as TAction).Enabled := frmSyncPhonebook.Visible;
  9240. end;
  9241.  
  9242. procedure TForm1.ActionContactsImportMEExecute(Sender: TObject);
  9243. begin
  9244.   frmSyncPhonebook.ImportContacts1.Click;
  9245. end;
  9246.  
  9247. procedure TForm1.DoAbort;
  9248. begin
  9249.   {
  9250.   if FObexConnecting then
  9251.     FObex.ForceAbort
  9252.   else
  9253.     if FObex.Connected and not FBusy then
  9254.       FObex.Abort
  9255.     else
  9256.       if not FAbort then begin
  9257.         Debug('Abort called');
  9258.         FAbort := True;
  9259.         if Assigned(ActiveThread) then ActiveThread.Terminate;
  9260.       end;
  9261.   {}
  9262.   if FBusy then begin
  9263.     // Display debug info only once
  9264.     if not FAbort then begin
  9265.       Debug('Abort called');
  9266.       FAbort := True;
  9267.       { TODO: Abort sending SMS with TxAndWait('AT+CMGS='...) command }
  9268.       if Assigned(ActiveThread) then ActiveThread.Terminate;
  9269.     end;
  9270.   end
  9271.   else
  9272.     if FObexConnecting then
  9273.       FObex.ForceAbort
  9274.     else
  9275.       FObex.Abort;
  9276.   {}    
  9277. end;
  9278.  
  9279. procedure TForm1.UpdateMEPhonebook;
  9280. var
  9281.   sl: TStrings;
  9282. begin
  9283.   sl := FNodeContactsME.data;
  9284.   if FStartupOptions.NoIRMC then
  9285.     ParsePhonebookListFromEditor(FNodeContactsME)
  9286.   else
  9287.     ParsePhonebookListFromSync(sl);
  9288.   RenderContactList(FNodeContactsME);
  9289.   { Update database } 
  9290.   SaveData;
  9291. end;
  9292.  
  9293. procedure TForm1.UpdateSMPhonebook;
  9294. begin
  9295.   ParsePhonebookListFromEditor(FNodeContactsSM);
  9296.   RenderContactList(FNodeContactsSM);
  9297.   { Update database }
  9298.   SaveData;
  9299. end;
  9300.  
  9301. procedure TForm1.ParsePhonebookListFromEditor(ANode: TtntTreeNode);
  9302. var
  9303.   NeedRefresh: boolean;
  9304.   Node :PVirtualNode;
  9305.   contact: PSIMData;
  9306.   s,where: string;
  9307.   sl: TStrings;
  9308. begin
  9309.   NeedRefresh := False;
  9310.   if ANode = FNodeContactsME then where := 'ME' else where := 'SM';
  9311.   sl := ANode.Data;
  9312.   sl.Clear;
  9313.   Node := frmSIMEdit.ListNumbers.GetFirst;
  9314.   if Node <> nil then
  9315.     repeat
  9316.       contact := frmSIMEdit.ListNumbers.GetNodeData(Node);
  9317.       s := contact^.cname;
  9318.       if contact^.ptype <> '' then s := s + '/' + UpperCase(contact^.ptype);
  9319.       { Update position if unknown } 
  9320.       if FConnected and (contact^.position = 0) then begin
  9321.         Status('Updating contact positions...');
  9322.         contact^.position := LocatePBIndex(where,contact^.cname,contact^.pnumb);
  9323.       end;
  9324.       if contact^.position = 0 then
  9325.         NeedRefresh := True;
  9326.       sl.Add('"' + s + '",' + contact^.pnumb + ',' +
  9327.         IntToStr(contact^.position) + ',' + IntToStr(contact^.imageindex));
  9328.       Application.ProcessMessages;
  9329.       Node := frmSIMEdit.ListNumbers.GetNext(Node);
  9330.     until Node = nil;
  9331.   TStringList(sl).Sort;
  9332.   if NeedRefresh then begin
  9333.     frmSIMEdit.ListNumbers.Repaint;
  9334.     if ANode = FNodeContactsME then where := 'Phone' else where := 'SIM';
  9335.     ShowMessage('The '+where+' Memory should be Refreshed as soon as possible, since some contact positions are not available!');
  9336.   end;
  9337. end;
  9338.  
  9339. procedure TForm1.DebugTools1Click(Sender: TObject);
  9340. begin
  9341.   PanelTest.Visible := not PanelTest.Visible;
  9342.   PanelTest.Enabled := PanelTest.Visible;
  9343.   DebugTools1.Checked := PanelTest.Visible;
  9344.   Explorer.Selected := Explorer.Items.GetFirstNode;
  9345.   ExplorerChange(nil,Explorer.Selected);
  9346. end;
  9347.  
  9348. procedure TForm1.ScriptControlCallFunction(Sender: TObject;
  9349.   const FunctionName: String; const Params: array of Variant);
  9350. var
  9351.   cmd: String;
  9352. begin
  9353.   FScriptRunning := FConnected;
  9354.   FScriptErrorOccur := False;
  9355.   if AnsiCompareText(__fma_objcall,FunctionName) <> 0 then
  9356.     cmd := FunctionName
  9357.   else
  9358.     cmd := Params[Low(Params)];
  9359.   if cmd <> '' then Debug('Script: Calling '+cmd)
  9360. end;
  9361.  
  9362. procedure TForm1.ScheduleScriptEvent(const FunctionName: string;
  9363.   const Params: array of Variant);
  9364. const
  9365.   sem: boolean = False;  
  9366. var
  9367.   i: integer;
  9368. begin
  9369.   while Timer3.Enabled or sem do begin
  9370.     Application.ProcessMessages;
  9371.     if Application.Terminated then Abort;
  9372.   end;
  9373.   try
  9374.     sem := True;
  9375.     try
  9376.       FScriptEventName := FunctionName;
  9377.       SetLength(FScriptEventParams,High(Params)-Low(Params)+1);
  9378.       for i := Low(Params) to High(Params) do
  9379.         FScriptEventParams[i] := Params[i];
  9380.       Timer3.Enabled := True;
  9381.     finally
  9382.       sem := False;
  9383.     end;
  9384.   except
  9385.     on e: exception do Debug('Internal error: '+e.Message);
  9386.   end;  
  9387. end;
  9388.  
  9389. procedure TForm1.Timer3Timer(Sender: TObject);
  9390. var
  9391.   s: string;
  9392. begin
  9393.   if FBusy or FWaitingOK then exit;
  9394.   Timer3.Enabled := False;
  9395.   if FamCommand <> '' then begin
  9396.     if FConnected and not FObex.Connected and not FObexConnecting then
  9397.       try
  9398.         s := FamCommand;
  9399.         if s <> '' then begin
  9400.           FamCommand := '';
  9401.           Debug('Script: Transmit Command...');
  9402.           Timer3.Enabled := FScriptEventName <> '';
  9403.           TxAndWait(s);
  9404.           Debug('Script: Transmit Done');
  9405.         end;
  9406.       except
  9407.         Status('Script: Transmit Error!');
  9408.       end
  9409.     else
  9410.       FamCommand := '';
  9411.     Timer3.Enabled := FScriptEventName <> '';
  9412.   end
  9413.   else begin
  9414.     s := FScriptEventName;
  9415.     FScriptEventName := '';
  9416.     Timer3.Enabled := FamCommand <> '';
  9417.     ScriptEvent(s,FScriptEventParams);
  9418.   end;
  9419. end;
  9420.  
  9421. procedure TForm1.ScheduleTxAndWait(Data, WaitStr: String);
  9422. begin
  9423.   { Wait for previous scheduled command to finish }
  9424.   while Timer3.Enabled do begin
  9425.     Application.ProcessMessages;
  9426.     if Application.Terminated then Abort;
  9427.   end;
  9428.   if Trim(Data) <> '' then begin
  9429.     FamCommand := Data;
  9430.     Debug('Scheduling Transmit Command '+Copy(Data,1,7)+'...');
  9431.     Timer3.Enabled := not Application.Terminated;
  9432.   end;  
  9433. end;
  9434.  
  9435. procedure TForm1.DisableKeyMonitor(TxDelay: boolean);
  9436. begin
  9437.   Debug('Disable Keypad Event Reporting');
  9438.   try
  9439.     if TxDelay then ScheduleTxAndWait('AT+CMER=0,0')
  9440.       else TxAndWait('AT+CMER=0,0'); // 0 = unset keypad monitoring
  9441.     FKeyMonitoring := False;
  9442.   except
  9443.   end;
  9444. end;
  9445.  
  9446. procedure TForm1.ActionSyncWithOutlookExecute(Sender: TObject);
  9447. var 
  9448.   SynchronizeContacts: TSynchronizeContacts;
  9449.   dlg: TfrmConnect;
  9450.   ID: String;
  9451.   Fullpath: String;
  9452.   ConfirmActions: TContactActions;
  9453.   I: Integer;
  9454. begin
  9455.   Status('Outlook Synchronize started');
  9456.   try
  9457.     { Sync with Outlook }
  9458.     ID := PhoneIdentity;
  9459.     Fullpath := ExePath;
  9460.     if ID <> '' then
  9461.       Fullpath := ExePath+'data\'+ID+'\dat\';
  9462.  
  9463.     FAutolinkContacts := False;
  9464.     ActionSyncPhonebook.Enabled := False;
  9465.     for I := Integer(Low(TContactAction)) to Integer(High(TContactAction)) do
  9466.       FOutlookConfirmed[TContactAction(I)] := cfNone;
  9467.  
  9468.     dlg := GetProgressDialog;
  9469.     //frmInfoView.linkSyncOutlook.Enabled := False;
  9470.     try
  9471.       if CanShowProgress then
  9472.         dlg.ShowProgress(FProgressLongOnly);
  9473.       dlg.SetDescr('Synchronizing contacts');
  9474.  
  9475.       SynchronizeContacts := TSynchronizeContacts.Create;
  9476.       try
  9477.         SynchronizeContacts.FileName := Fullpath + 'ContactSync.xml';
  9478.         SynchronizeContacts.FMA := TFMAContactSource.Create;
  9479.         SynchronizeContacts.Extern := TOutlookContactSource.Create;
  9480.         try
  9481.           SynchronizeContacts.OnConflict := SyncContactsConflict;
  9482.           SynchronizeContacts.OnFirstTime := SyncContactsFirstTime;
  9483.           SynchronizeContacts.OnError := SyncContactsError;
  9484.           SynchronizeContacts.OnConfirm := SyncContactsConfirm;
  9485.           SynchronizeContacts.OnChooseLink := SyncContactsChooseLink;
  9486.  
  9487.           if FOutlookConfirmAdding then
  9488.             Include(ConfirmActions, caAdd);
  9489.           if FOutlookConfirmUpdating then
  9490.             Include(ConfirmActions, caUpdate);
  9491.           if FOutlookConfirmDeleting then
  9492.             Include(ConfirmActions, caDelete);
  9493.           SynchronizeContacts.FMA.ConfirmActions := ConfirmActions;
  9494.           SynchronizeContacts.Extern.ConfirmActions := ConfirmActions;
  9495.  
  9496.            with SynchronizeContacts.Extern as TOutlookContactSource do begin
  9497.              Categories.DelimitedText := FOutlookCategories;
  9498.              Folders.DelimitedText := FSelectedOutlookFolders;
  9499.              NewContactsFolder := FOutlookNewContactsFolder;
  9500.            end;
  9501.  
  9502.           dlg.SetDescr('Loading contacts');
  9503.           SynchronizeContacts.Load;
  9504.           if not FAbortDetected then begin
  9505.             dlg.SetDescr('Synchronizing contacts');
  9506.             SynchronizeContacts.Synchronize;
  9507.             dlg.SetDescr('Saving contacts');
  9508.             SynchronizeContacts.Save;
  9509.           end;
  9510.         finally
  9511.           SynchronizeContacts.FMA.Free;
  9512.           SynchronizeContacts.Extern.Free;
  9513.         end;
  9514.       finally
  9515.         SynchronizeContacts.Free;
  9516.       end;
  9517.     finally
  9518.       //frmInfoView.linkSyncOutlook.Enabled := True;
  9519.       FreeProgressDialog;
  9520.       ActionSyncPhonebook.Enabled := True;
  9521.       with frmSyncPhonebook do
  9522.         ListContacts.Sort(nil, ListContacts.Header.SortColumn, ListContacts.Header.SortDirection);
  9523.       UpdateMEPhonebook;
  9524.     end;
  9525.     Status('Outlook Synchronize completed');
  9526.   except
  9527.     on E: Exception do begin
  9528.       SyncLogFmt('Error: Synchronize aborted (%s: %s)', [E.ClassName, E.Message]);
  9529.       Status(Format('Error: Outlook Synchronize aborted (%s: %s)', [E.ClassName, E.Message]));
  9530.       MessageDlg(Format('Error: Outlook Synchronize aborted (%s: %s)', [E.ClassName, E.Message]),mtError,[mbOk],0);
  9531.     end;
  9532.   end;
  9533. end;
  9534.  
  9535. procedure TForm1.SyncContactsConflict(Sender: TObject; Contact: TContact; const 
  9536.     Description: WideString; const Item0Name, Item1Name: String; var 
  9537.     SelectedItem: Integer);
  9538. begin
  9539.   if FOutlookSyncConflict = 0 then begin
  9540.     SelectedItem := 1;
  9541.   end
  9542.   else if FOutlookSyncConflict = 1 then begin
  9543.     SelectedItem := 0;
  9544.   end
  9545.   else begin
  9546.     frmPromptConflict := TfrmPromptConflict.Create(Self);
  9547.     try
  9548.       frmPromptConflict.Contact := Contact.FullName;
  9549.       frmPromptConflict.Info := Description;
  9550.       frmPromptConflict.Item0Name := Item0Name;
  9551.       frmPromptConflict.Item1Name := Item1Name;
  9552.       frmPromptConflict.SelectedItem := SelectedItem;
  9553.       if frmPromptConflict.ShowModal = mrOK then
  9554.         SelectedItem := frmPromptConflict.SelectedItem
  9555.       else
  9556.         SelectedItem := -1;
  9557.     finally
  9558.       frmPromptConflict.Free;
  9559.     end;
  9560.   end;
  9561. end;
  9562.  
  9563. procedure TForm1.ActionSyncWithOutlookUpdate(Sender: TObject);
  9564. begin
  9565.   ActionSyncWithOutlook.Enabled := ActionSyncPhonebook.Enabled and not FStartupOptions.NoIRMC;
  9566. end;
  9567.  
  9568. resourcestring
  9569.   SSyncContactsFirstTime = 'This is the first time you have started Outlook Synchronization. ' +
  9570.                            'All FMA contacts will be added to Outlook and all Outlook contacts ' +
  9571.                            'will be added to FMA, unless you choose to link them. ' +
  9572.                            'The contacts will be linked after that.' + #13#10 +
  9573.                            #13#10 +
  9574.                            'Make sure you have made a backup of your FMA and Outlook contacts!' + #13#10 +
  9575.                            #13#10 +
  9576.                            'There is a maximum of %d contacts in the phonebook memory.' + #13#10 +
  9577.                            #13#10 +
  9578.                            'Do you want to continue?';
  9579.  
  9580. procedure TForm1.SyncContactsFirstTime(Sender: TObject; var Continue: Boolean);
  9581. begin
  9582.   Continue := MessageDlg(PChar(Format(SSyncContactsFirstTime, [frmSyncPhonebook.FMaxRecME])), mtConfirmation, [mbNo,mbYes], 0) = ID_YES;
  9583. end;
  9584.  
  9585. procedure TForm1.SyncContactsError(Sender: TObject; const Message: String);
  9586. begin
  9587.   SyncLogFmt('Error: Synchronize aborted (%s)', [Message]);
  9588.   Status(Format('Error: Outlook Synchronize aborted (%s)', [Message]));
  9589.   MessageDlg(Format('Error: Outlook Synchronize aborted (%s)', [Message]), mtError, [mbOk], 0);
  9590. end;
  9591.  
  9592. resourcestring
  9593.   SSyncContactsConfirm = '%s.' +
  9594.                          #13#10 + #13#10 +
  9595.                          'Is this ok?';
  9596.  
  9597. procedure TForm1.SyncContactsConfirm(Sender: TObject; Contact: TContact; 
  9598.     Action: TContactAction; const Description: WideString; var Confirmed: 
  9599.     Boolean);
  9600.  
  9601. begin
  9602.   case FOutlookConfirmed[Action] of
  9603.     cfYesToAll: Confirmed := True;
  9604.     cfNoToAll: Confirmed := False;
  9605.     else begin
  9606.       case MessageDlg(WideFormat(SSyncContactsConfirm, [Description]), mtConfirmation, [mbNo,mbYes,mbYesToAll,mbNoToAll], 0) of
  9607.         mrYes: Confirmed := True;
  9608.         mrYesToAll: begin
  9609.           Confirmed := True;
  9610.           FOutlookConfirmed[Action] := cfYesToAll;
  9611.         end;
  9612.         mrNoToAll: begin
  9613.           Confirmed := False;
  9614.           FOutlookConfirmed[Action] := cfNoToAll;
  9615.         end;
  9616.         else Confirmed := False;
  9617.       end;
  9618.     end;
  9619.   end;
  9620. end;
  9621.  
  9622. procedure TForm1.SyncContactsChooseLink(Sender: TObject; Contact: TContact;
  9623.   PossibleLinks: TPossibleLinks; var OtherContact: TContact);
  9624. var
  9625.   frmChooseLink: TfrmChooseLink;
  9626.   LinkResult: TModalResult;
  9627. begin
  9628.   if FOutlookNewAction = 0 then begin
  9629.     frmChooseLink := TfrmChooseLink.Create(nil);
  9630.     try
  9631.       frmChooseLink.Contact := Contact;
  9632.       frmChooseLink.PossibleLinks := PossibleLinks;
  9633.       if FAutolinkContacts then
  9634.         if frmChooseLink.OtherContact(True) <> nil then
  9635.           LinkResult := mrAll // link to
  9636.         else
  9637.           LinkResult := mrIgnore // as new
  9638.       else
  9639.         LinkResult := frmChooseLink.ShowModal;
  9640.       case LinkResult of
  9641.         mrCancel:
  9642.           raise ESynchronize.Create('Contacts linking aborted by user');
  9643.         mrOk:
  9644.           OtherContact := frmChooseLink.OtherContact;
  9645.         mrAll: begin
  9646.           OtherContact := frmChooseLink.OtherContact(True);
  9647.           FAutolinkContacts := True;
  9648.         end;
  9649.       end;
  9650.     finally
  9651.       frmChooseLink.Free;
  9652.     end;
  9653.   end;
  9654. end;
  9655.  
  9656. procedure TForm1.CallScriptMethod(FunctionName: string; Params: array of Variant);
  9657. var
  9658.   NewParams: array of Variant;
  9659.   HasParams: boolean;
  9660. begin
  9661.   HasParams := Length(Params) > 0;
  9662.   if Pos('.',FunctionName) <> 0 then begin
  9663.     { calling object's method }
  9664.     if HasParams then begin
  9665.       { ...with params }
  9666.       SetLength(NewParams,2);
  9667.       NewParams[Low(NewParams)] := VarAsType(FunctionName,varString);
  9668.       NewParams[Low(NewParams)+1] := VarArrayOf(Params);
  9669.       ScriptControl.CallFunction(__fma_objcall+'Ex', NewParams);
  9670.     end
  9671.     else begin
  9672.       { ...without params }
  9673.       SetLength(NewParams,1);
  9674.       NewParams[Low(NewParams)] := VarAsType(FunctionName,varString);
  9675.       ScriptControl.CallFunction(__fma_objcall, NewParams);
  9676.     end;
  9677.   end
  9678.   else
  9679.     { Dako - I have strange error here using D6 "Variant array index out of bounds" :-o See bellow }
  9680.     ScriptControl.CallFunction(FunctionName, Params);
  9681.     (*
  9682.     try
  9683.       { calling regular function }
  9684.       ScriptControl.CallFunction(FunctionName, Params);
  9685.     except
  9686.       { Workaround! Ignore error when no params are sent (new version aw_SCtl.pas bug?) }
  9687.       on E: Exception do begin
  9688.         if not (E is EVariantError) then
  9689.           raise E;
  9690.       end;
  9691.     end;
  9692.     *)
  9693. end;
  9694.  
  9695. procedure TForm1.CheckforUpdate2Click(Sender: TObject);
  9696. begin
  9697.   CheckforUpdate1.Enabled := False;
  9698.   try
  9699.     // TODO: add support for update mirrors
  9700.     // mirror_1: http://fma.sourceforge.net/updates
  9701.     // mirror_2: http://5group.com/~zdravko/fma/updates
  9702.     FmaWebUpdate1.CheckforUpdate(ExtractFileVersionInfo(Application.ExeName,'FileVersion') + BuildPatchLetter);
  9703.   finally
  9704.     CheckforUpdate1.Enabled := True;
  9705.   end;
  9706. end;
  9707.  
  9708. procedure TForm1.FmaWebUpdate1BeforeUpdate(Sender: TObject; var AllowRestart: Boolean);
  9709. begin
  9710.   if FConnected then ActionConnectionDisconnect.Execute;
  9711.   AllowRestart := not FConnected;
  9712.   if AllowRestart then ActionExit.Execute;
  9713. end;
  9714.  
  9715. procedure TForm1.FmaWebUpdate1Error(Sender: TObject; Message: String);
  9716. begin
  9717.   MessageDlg(Message, mtError, [mbOk], 0);
  9718. end;
  9719.  
  9720. function TForm1.IsScriptInitialized: boolean;
  9721. begin
  9722.   { True if no script at all or when script OnInit is called }
  9723.   Result := (FScriptFile = '') or not FileExists(FScriptFile) or FScriptInitialized;
  9724. end;
  9725.  
  9726. procedure TForm1.ClearExplorerViews;
  9727.   procedure ClearNode(var Node: TTntTreeNode; ClearData: boolean = True);
  9728.   begin
  9729.     Node.DeleteChildren;
  9730.     if ClearData then TStrings(Node.Data).Clear;
  9731.   end;
  9732.   procedure ClearChildren(var Node: TTntTreeNode; ClearData: boolean = False);
  9733.   var
  9734.     i: integer;
  9735.   begin
  9736.     for i := 0 to Node.Count-1 do begin
  9737.       Node[i].DeleteChildren;
  9738.     end;
  9739.     if ClearData then TStrings(Node.Data).Clear;
  9740.   end;
  9741. begin
  9742.   Debug('Database: Unload all data and clear views...');
  9743.   FLookupList.Clear;
  9744.   try
  9745.     ClearNode(FNodeMsgInbox);
  9746.     ClearNode(FNodeMsgOutbox);
  9747.     ClearNode(FNodeMsgSent);
  9748.     ClearNode(FNodeMsgArchive);
  9749.     ClearNode(FNodeMsgDrafts);
  9750.     ClearNode(FNodeContactsME);
  9751.     ClearNode(FNodeContactsSM);
  9752.     ClearNode(FNodeCallsIn);
  9753.     ClearNode(FNodeCallsOut);
  9754.     ClearNode(FNodeCallsMissed);
  9755.     ClearNode(FNodeBookmarks);
  9756.     ClearChildren(FNodeOrganizer);
  9757.     FNodeObex.DeleteChildren;
  9758.     FNodeProfiles.DeleteChildren;
  9759.     FNodeGroups.DeleteChildren;
  9760.   finally
  9761.     FDatabaseLoaded := False;
  9762.     ExplorerChange(Explorer,Explorer.Selected);
  9763.   end;
  9764.   Debug('Database: Unload done');
  9765. end;
  9766.  
  9767. function TForm1.GetNextLongSMSRefference: string;
  9768. var
  9769.   mref: integer;
  9770. begin
  9771.   randomize;
  9772.   mref := 1 + random(252);
  9773.   with TRegistry.Create do
  9774.     try
  9775.       RootKey := HKEY_CURRENT_USER;
  9776.       if OpenKey('Software\floAt\fma',true) then
  9777.         try
  9778.           if ValueExists('MessageRef') then
  9779.             mref := ReadInteger('MessageRef');
  9780.           if (mref < 0) or (mref >= MAXBYTE) then mref := 0;
  9781.           inc(mref);
  9782.           WriteInteger('MessageRef',mref);
  9783.         finally
  9784.           CloseKey;
  9785.         end;
  9786.     finally
  9787.       Free;
  9788.     end;
  9789.   Result := IntToHex(mref, 2);
  9790. end;
  9791.  
  9792. procedure TForm1.ViewInitialize;
  9793. begin
  9794.   { Set startup folder, if specified }
  9795.   case FExplorerStartupMode of
  9796.     0: Explorer.Selected := Explorer.Items.GetFirstNode;
  9797.     1: Explorer.Selected := FNodeMsgInbox;
  9798.     2: Explorer.Selected := FNodeMsgArchive;
  9799.     3: Explorer.Selected := FNodeContactsME;
  9800.     4: Explorer.Selected := FNodeContactsSM;
  9801.     5: Explorer.Selected := FNodeOrganizer;
  9802.   end;
  9803.   ExplorerChange(Explorer,Explorer.Selected);
  9804.  
  9805.   if FormStorage1.StoredValue['ActivityLog'] = True then
  9806.     GetActivityLogWindow.Show;
  9807.   if FormStorage1.StoredValue['SyncLog'] = True then
  9808.     GetSyncLogWindow.Show;
  9809.   if FormStorage1.StoredValue['DebugLog'] = True then
  9810.     if frmDebug <> nil then frmDebug.Show;
  9811. end;
  9812.  
  9813. procedure TForm1.ActionSwitchUserProfileUpdate(Sender: TObject);
  9814. begin
  9815.   { Allow DB profile change only in Offline mode }
  9816.   ActionSwitchUserProfile.Enabled := ActionConnectionConnect.Enabled;
  9817. end;
  9818.  
  9819. procedure TForm1.ActionSwitchUserProfileExecute(Sender: TObject);
  9820. begin
  9821.   with TfrmOfflineProfile.Create(nil) do
  9822.     try
  9823.       if ShowModal = mrOk then begin
  9824.         SaveData;
  9825.         LoadPhoneDataFiles(SelectedProfile);
  9826.       end;
  9827.     finally
  9828.       free;
  9829.     end;
  9830. end;
  9831.  
  9832. function TForm1.ExtractPhoneIdentity(var Model, Serial: string): string;
  9833. begin
  9834.   serial := StringReplace(serial,'"','',[rfReplaceAll]);
  9835.   serial := StringReplace(serial,':','-',[rfReplaceAll]);
  9836.   serial := StringReplace(serial,'\','-',[rfReplaceAll]);
  9837.   serial := StringReplace(serial,'/','-',[rfReplaceAll]);
  9838.   Result := model+' ['+serial+']';
  9839. end;
  9840.  
  9841. function TForm1.GetPhoneIdentity: string;
  9842. begin
  9843.   Result := FormStorage1.StoredValue['LastIdentity'];
  9844. end;
  9845.  
  9846. procedure TForm1.SetPhoneIdentity(ID: string);
  9847. begin
  9848.   FormStorage1.StoredValue['LastIdentity'] := ID;
  9849. end;
  9850.  
  9851. function TForm1.GetNewMessagesCounter(rootNode: TtntTreeNode): integer;
  9852. var
  9853.   s: WideString;
  9854.   i: integer;
  9855. begin
  9856.   s := rootNode.Text;
  9857.   i := Pos(' (',s);
  9858.   if i <> 0 then begin
  9859.     Delete(s,1,i+1);       // remove "text ("
  9860.     Delete(s,Length(s),1); // remove tail ")"
  9861.     Result := StrToInt(s);
  9862.   end
  9863.   else
  9864.     Result := 0;
  9865. end;
  9866.  
  9867. function TForm1.IsEBCAEnabled: boolean;
  9868. begin
  9869.   Result := EBCALastState = 1;
  9870. end;
  9871.  
  9872. function TForm1.CanUseEBCA(IgnoreConnectingState: boolean): boolean;
  9873. begin
  9874.   { Do not enable monitoring while minimized, in Obex, or disconnected }
  9875.   Result := FUseEBCA and FStateMonitor and FConnected and not FObex.Connected and not FObexConnecting and
  9876.     (FormStorage1.StoredValue['StartMinimized'] = False);
  9877.   if not IgnoreConnectingState and not FConnectingComplete then
  9878.     Result := False;
  9879. end;
  9880.  
  9881. procedure TForm1.DownloadMessages(Node: TtntTreeNode);
  9882. var
  9883.   sl: TStrings;
  9884.   frmConnect: TfrmConnect;
  9885. begin
  9886.   Status('Downloading Messages...');
  9887.   sl := Node.Data;
  9888.   frmInfoView.linkGetMessages.Enabled := False;
  9889.   frmConnect := GetProgressDialog;
  9890.   try
  9891.     if CanShowProgress then
  9892.       frmConnect.ShowProgress(FProgressLongOnly);
  9893.     case (Node.StateIndex and $3F0000) of
  9894.       $210000:
  9895.         begin
  9896.           sl.Clear;
  9897.           frmConnect.SetDescr('Downloading read messages');
  9898.           DownloadSMS(1,Node);
  9899.           frmConnect.SetDescr('Downloading unread messages');
  9900.           DownloadSMS(0,Node);
  9901.         end;
  9902.       $220000:
  9903.         begin
  9904.           sl.Clear;
  9905.           frmConnect.SetDescr('Downloading sent messages');
  9906.           DownloadSMS(3,Node);
  9907.         end;
  9908.     end;
  9909.     frmConnect.SetDescr('Saving messages data');
  9910.     Debug('Startup: Saving messages data');
  9911.     if frmMsgView.Visible then frmMsgView.RenderListView(sl);
  9912.     { Update database }
  9913.     SaveData;
  9914.   finally
  9915.     FreeProgressDialog;
  9916.     frmInfoView.linkGetMessages.Enabled := True;
  9917.   end;
  9918.   Status('Messages downloaded');
  9919. end;
  9920.  
  9921. procedure TForm1.ToolButton15Click(Sender: TObject);
  9922. begin
  9923.   Explorer.Selected := Explorer.Items.GetFirstNode;
  9924.   if ActionConnectionExplorer.Checked then
  9925.     ActionConnectionExplorer.Execute;
  9926. end;
  9927.  
  9928. procedure TForm1.CoolTrayIcon1BalloonHintClick(Sender: TObject);
  9929. begin
  9930.   // TODO: Check why FLastBaloonMessagePDU is empty here on New SMS text baloon click ???
  9931.   if FLastBaloonMessagePDU <> '' then begin
  9932.     { Make new message as read }
  9933.     if IsMoveToArchiveEnabled then
  9934.       UpdateNewMessagesCounter(FNodeMsgArchive,FLastBaloonMessagePDU)
  9935.     else
  9936.       UpdateNewMessagesCounter(FNodeMsgInbox,FLastBaloonMessagePDU);
  9937.     FLastBaloonMessagePDU := '';
  9938.   end
  9939.   else
  9940.     if FormStorage1.StoredValue['StartMinimized'] = True then
  9941.       ActionWindowRestore.Execute
  9942.     else
  9943.       Application.BringToFront;
  9944. end;
  9945.  
  9946. procedure TForm1.ActionViewActivityLogUpdate(Sender: TObject);
  9947. begin
  9948.   ActionViewActivityLog.Checked := GetActivityLogWindow.Visible;
  9949. end;
  9950.  
  9951. procedure TForm1.ActionViewActivityLogExecute(Sender: TObject);
  9952. var
  9953.   Dlg: TfrmActivityLog;
  9954. begin
  9955.   Dlg := GetActivityLogWindow;
  9956.   if Dlg.Visible then Dlg.Close else Dlg.Show;
  9957.   FormStorage1.StoredValue['ActivityLog'] := Dlg.Visible;
  9958. end;
  9959.  
  9960. procedure TForm1.AddCall(Node: TtntTreeNode; contact: WideString;
  9961.   time: string; AsFirst: boolean);
  9962. var
  9963.   itm: TTntTreeNode;
  9964. begin
  9965.   if AsFirst then begin
  9966.     itm := Explorer.Items.AddChildFirst(Node,contact);
  9967.     TStrings(Node.Data).Insert(0,'"'+contact+'","'+time+'"');
  9968.   end
  9969.   else begin
  9970.     itm := Explorer.Items.AddChild(Node,contact);
  9971.     TStrings(Node.Data).Add('"'+contact+'","'+time+'"');
  9972.   end;
  9973.   with itm do begin
  9974.     ImageIndex := 52 + (Node.StateIndex and $0F0000) shr 16;
  9975.     StateIndex := Node.Count;
  9976.   end;
  9977.   if (Node = FNodeCallsMissed) and (frmMissedCalls <> nil) then
  9978.     with frmMissedCalls.MissedCalls.Items.Add do begin
  9979.       Caption := contact;
  9980.       SubItems.Add(time);
  9981.       ImageIndex := 16;
  9982.     end;
  9983.   if AsFirst then ReindexCallsNode(Node);
  9984. end;
  9985.  
  9986. procedure TForm1.InitCalls(Node: TtntTreeNode);
  9987. var
  9988.   k,j,m: integer;
  9989.   dtm,typ,str,num,buffer,start,stop: String;
  9990.   sl,it,slTmp: TStringList;
  9991.   grp: TTntTreeNode;
  9992.   s: WideString;
  9993. begin
  9994.   Node.DeleteChildren;
  9995.   TStrings(Node.Data).Clear;
  9996.   if Node = FNodeCallsMissed then frmMissedCalls.MissedCalls.Clear;
  9997.   if frmInfoView.Visible then EBCAState(False);
  9998.   { Retrieve Calls now }
  9999.   sl := TStringList.Create;
  10000.   it := TStringList.Create;
  10001.   try
  10002.     grp := Node;
  10003.     Debug('Loading '+grp.Text+' calls...');
  10004.     with grp do begin
  10005.       if grp = FNodeCallsIn then TxAndWait('AT+CPBS="RC"')
  10006.       else
  10007.       if grp = FNodeCallsOut then TxAndWait('AT+CPBS="DC"')
  10008.       else
  10009.       if grp = FNodeCallsMissed then TxAndWait('AT+CPBS="MC"')
  10010.       else
  10011.         Abort;
  10012.       TxAndWait('AT+CPBR=?');
  10013.       buffer := '';
  10014.       for m := 0 to FRxBuffer.Count-1 do
  10015.         if Pos('+CPBR',FRxBuffer[m]) = 1 then begin
  10016.           buffer := FRxBuffer[m];
  10017.           for k := 1 to length(buffer) do begin
  10018.             if IsDelimiter('()-', buffer, k) then buffer[k] := ' ';
  10019.           end;
  10020.           break;
  10021.         end;
  10022.       if buffer <> '' then begin
  10023.         slTmp := TStringList.Create;
  10024.         try
  10025.           slTmp.DelimitedText := buffer;
  10026.           start := slTmp.Strings[1];
  10027.           stop := slTmp.Strings[2];
  10028.           TxAndWait('AT+CPBR=' + start + ',' + stop);
  10029.           if grp = FNodeCallsMissed then
  10030.             frmMissedCalls.MissedCalls.Clear;
  10031.           it.Clear; // clear items frmo previous group, 10x to Mindstormpt
  10032.           it.AddStrings(FRxBuffer);
  10033.           //idx := 1;
  10034.           for j := 0 to it.Count - 2 do begin
  10035.             if pos('+CPBR', it[j]) = 1 then begin
  10036.               // could receive this for unknown number ?
  10037.               //   +CPBR: 7,"",145,"","2004/03/20,12:55"
  10038.               s := FRxBuffer.Strings[j];
  10039.               if FUseUTF8 then s := UTF8Decode(s);
  10040.               buffer := s;
  10041.               k := Pos('"',buffer);
  10042.               System.Delete(buffer,1,k-1); // remove up to 1st "
  10043.               slTmp.DelimitedText := buffer;
  10044.               num := slTmp[0];
  10045.               typ := slTmp[1];
  10046.               str := slTmp[2];
  10047.               dtm := slTmp[3];
  10048.               if (num <> '') and (typ = '145') and (num[1] <> '+') then
  10049.                 num := '+' + num;
  10050.               if str = '' then
  10051.                 { see uMissedCalls for details about when
  10052.                   sUnknownContact and when sUnknownNumber is used }
  10053.                 if num <> '' then str := sUnknownContact
  10054.                   else str := sUnknownNumber;
  10055.               if num <> '' then str := str + ' [' + num + ']';
  10056.               AddCall(grp,str,dtm);
  10057.             end;
  10058.           end;
  10059.         finally
  10060.           slTmp.Free;
  10061.         end;
  10062.       end;
  10063.     end;
  10064.     if not CoolTrayIcon1.CycleIcons then
  10065.       Status('');
  10066.   finally
  10067.     sl.Free;
  10068.     it.Free;
  10069.     if frmInfoView.Visible then begin
  10070.       frmInfoView.UpdateWelcomePage(True);
  10071.       EBCAState(True);
  10072.     end;
  10073.     if frmExplore.Visible then frmExplore.RootNode := Explorer.Selected;
  10074.   end;
  10075.   //UpdateMEPhonebook;
  10076. end;
  10077.  
  10078. procedure TForm1.ReindexCallsNode(Node: TTntTreeNode);
  10079. var
  10080.   i: integer;
  10081. begin
  10082.   for i := 0 to Node.Count-1 do
  10083.     Node.Item[i].StateIndex := i+1;
  10084. end;
  10085.  
  10086. function TForm1.ContactNumberByTel(ContactNumber: string): string;
  10087. begin
  10088.   if (ContactNumber <> '') and (ContactNumber <> sUnknownNumber) then
  10089.     Result := LookupContact(ContactNumber,sUnknownContact)+' ['+ContactNumber+']'
  10090.   else
  10091.     Result := sUnknownNumber;
  10092. end;
  10093.  
  10094. function TForm1.ContactNumberByName(ContactName: string): string;
  10095. var
  10096.   contact: PContactData;
  10097. begin
  10098.   if frmSyncPhonebook.FindContact(ContactName,contact) then
  10099.     Result := GetContactFullName(contact) + ' [' + GetContactDefPhone(contact) + ']'
  10100.   else
  10101.     Result := sUnknownNumber;
  10102. end;
  10103.  
  10104. function TForm1.GetPartialNumber(Number: string): string;
  10105. begin
  10106.   Result := copy(Number, length(Number) - 7, 8);
  10107. end;
  10108.  
  10109. function TForm1.IsT610Clone: boolean;
  10110. var
  10111.   model: string;
  10112. begin
  10113.   model := StatusBar.Panels[1].Text;
  10114.   Result := (Pos('T610',model) <> 0) or // and T610 clones
  10115.             (Pos('T630',model) <> 0) or
  10116.             (Pos('Z600',model) <> 0) or
  10117.             (Pos('Z610',model) <> 0) or
  10118.             (Pos('K700',model) <> 0);
  10119. end;
  10120.  
  10121. procedure TForm1.ApplyEditorChanges;
  10122. var
  10123.   P: TPoint;
  10124.   T,L: integer;
  10125. begin
  10126.   try
  10127.     if frmEditor.Script.Modified then begin
  10128.       Status('Saving changes...');
  10129.       if FScriptFile <> '' then
  10130.         { Save changes to the script file }
  10131.         frmEditor.Script.Lines.SaveToFile(FScriptFile);
  10132.       { Apply changes to Script control? }  
  10133.       if not FExiting and not FExitWindows then begin
  10134.         { On exiting Fma/Windows do not update MS Script control }
  10135.         ScriptControl.Code.Assign(frmEditor.Script.Lines);
  10136.         frmEditor.Script.Modified := False;
  10137.         Status('Applying changes...');
  10138.         frmEditor.Script.Lines.BeginUpdate;
  10139.         P := frmEditor.Script.CaretXY;
  10140.         T := frmEditor.Script.TopLine;
  10141.         L := frmEditor.Script.LeftChar;
  10142.         try
  10143.           ScriptInitialize;
  10144.         finally
  10145.           frmEditor.Script.CaretXY := P;
  10146.           frmEditor.Script.TopLine := T;
  10147.           frmEditor.Script.LeftChar := L;
  10148.           frmEditor.Script.Lines.EndUpdate;
  10149.         end;
  10150.       end
  10151.       else
  10152.         frmEditor.Script.Modified := False;
  10153.     end;
  10154.     if frmEditor.MessagesVisible then Abort;
  10155.     Status('');
  10156.   except
  10157.     Status('Script contains errors or save failed!');
  10158.   end;
  10159. end;
  10160.  
  10161. procedure TForm1.ToolBar5CustomDrawButton(Sender: TToolBar;
  10162.   Button: TToolButton; State: TCustomDrawState; var DefaultDraw: Boolean);
  10163. const
  10164.   Sel: TToolButton = nil;
  10165. //var s: string;
  10166. begin
  10167. (*
  10168.   {
  10169.   s := '';
  10170.   if cdsHot in State then s := s + 'hot ';
  10171.   if cdsSelected in State then s := s + 'selected ';
  10172.   if cdsChecked in State then s := s + 'checked ';
  10173.   if cdsFocused in State then s := s + 'focused ';
  10174.   if cdsDefault in State then s := s + 'default ';
  10175.   Debug('Toolbar: '+Button.Caption+' ['+s+']');
  10176.   }
  10177.   if (cdsHot in State) and (cdsSelected in State) then begin
  10178.     Sel := Button;
  10179.     //Debug('Toolbar: '+Sel.Caption+' is selected');
  10180.     if Sel = FLastMenuButton then begin
  10181.       ReleaseMainMenuButton;
  10182.       Sel := nil;
  10183.     end;
  10184.   end;
  10185.   if (State = []) and (Button = Sel) then begin
  10186.     ReleaseMainMenuButton;
  10187.     Sel.Down := True;
  10188.     //Debug('Toolbar: '+Sel.Caption+' is down');
  10189.     FLastMenuButton := Sel;
  10190.     Sel := nil;
  10191.   end;
  10192. *)
  10193.   if cdsSelected in State then begin
  10194.     if FLastMenuButton <> Button then begin
  10195.       //Debug('Toolbar: '+Button.Caption+' is SEL');
  10196.       Sel := Button;
  10197.     end;
  10198.   end;
  10199.   if (State = []) and (Button = Sel) then begin
  10200.     if FLastMenuButton <> Button then begin
  10201.       ReleaseMainMenuButton;
  10202.       FLastMenuButton := Sel;
  10203.       Sel.Down := True;
  10204.       //Debug('Toolbar: '+Sel.Caption+' is DOWN');
  10205.       Sel := nil;
  10206.     end;
  10207.   end;
  10208. end;
  10209.  
  10210. procedure TForm1.ReleaseMainMenuButton;
  10211. begin
  10212.   if FLastMenuButton <> nil then begin
  10213.     FLastMenuButton.Down := False;
  10214.     //Debug('Toolbar: '+FLastMenuButton.Caption+' is UP');
  10215.     FLastMenuButton := nil;
  10216.   end;
  10217. end;
  10218.  
  10219. procedure TForm1.ApplicationEvents1Idle(Sender: TObject;
  10220.   var Done: Boolean);
  10221. begin
  10222.   if FLastMenuButton <> nil then
  10223.     { Update main menu tool button }
  10224.     //ToolBar5CustomDrawButton(ToolBar5,FLastMenuButton,[cdsHot,cdsSelected],Done);
  10225.     ReleaseMainMenuButton;
  10226. end;
  10227.  
  10228. procedure TForm1.ActivityLog(str: String; PrefixTimestamp: boolean);
  10229. begin
  10230.   if not Application.Terminated then
  10231.     DoLog(GetActivityLogWindow,str,PrefixTimestamp);
  10232. end;
  10233.  
  10234. procedure TForm1.SyncLog(str: String; PrefixTimestamp: boolean);
  10235. begin
  10236.   if not Application.Terminated then
  10237.     DoLog(GetSyncLogWindow,str,PrefixTimestamp);
  10238. end;
  10239.  
  10240. procedure TForm1.DoLog(Form: TfrmDebug; str: String;
  10241.   PrefixTimestamp: boolean);
  10242. var
  10243.   s,timestamp: String;
  10244. begin
  10245.   if (Form <> nil) and (Form.Memo <> nil) then
  10246.     with Form.Memo do begin
  10247.       if PrefixTimestamp then begin
  10248.         DateTimeToString(timestamp, 'hh:nn:ss:zzz', now);
  10249.         s := timestamp + ' ' + str;
  10250.       end
  10251.       else
  10252.         s := str;
  10253.       { Don't leave an empty line at window bottom }
  10254.       if Lines.Count <> 0 then s := #13#10 + s;
  10255.       SelStart := length(Text);
  10256.       SelText := s;
  10257.     end;
  10258. end;
  10259.  
  10260. procedure TForm1.ActionSyncLogUpdate(Sender: TObject);
  10261. begin
  10262.   ActionSyncLog.Checked := GetSyncLogWindow.Visible;
  10263. end;
  10264.  
  10265. procedure TForm1.ActionDebugLogUpdate(Sender: TObject);
  10266. begin
  10267.   ActionDebugLog.Visible := frmDebug <> nil;
  10268.   if ActionDebugLog.Visible then
  10269.     ActionDebugLog.Checked := frmDebug.Visible
  10270.   else
  10271.     ActionDebugLog.Checked := False;
  10272. end;
  10273.  
  10274. procedure TForm1.ActionDebugLogExecute(Sender: TObject);
  10275. begin
  10276.   if frmDebug <> nil then 
  10277.     if frmDebug.Visible then frmDebug.Close else frmDebug.Show;
  10278.   FormStorage1.StoredValue['DebugLog'] := (frmDebug <> nil) and frmDebug.Visible;
  10279. end;
  10280.  
  10281. procedure TForm1.PopupMenu2Popup(Sender: TObject);
  10282. begin
  10283.   ShowExplorer1.Checked := ActionConnectionExplorer.Checked;
  10284.   ShowCaption1.Checked := FShowTodayCaption;
  10285.   ShowDiagram1.Checked := FShowDiagram;
  10286. end;
  10287.  
  10288. procedure TForm1.ShowCaption1Click(Sender: TObject);
  10289. begin
  10290.   FShowTodayCaption := not FShowTodayCaption;
  10291.   FormStorage1.StoredValue['Today Caption'] := FShowTodayCaption;
  10292.   frmInfoView.UpdateWelcomePage;
  10293. end;
  10294.  
  10295. procedure TForm1.ShowDiagram1Click(Sender: TObject);
  10296. begin
  10297.   FShowDiagram := not FShowDiagram;
  10298.   FormStorage1.StoredValue['Phone Diagram'] := FShowDiagram;
  10299.   frmInfoView.UpdateWelcomePage;
  10300. end;
  10301.  
  10302. procedure TForm1.ActionContactsExportSMUpdate(Sender: TObject);
  10303. begin
  10304.   (Sender as TAction).Enabled := frmSIMEdit.Visible and (frmSIMEdit.ListNumbers.SelectedCount <> 0);
  10305. end;
  10306.  
  10307. procedure TForm1.ActionContactsExportSMExecute(Sender: TObject);
  10308. var
  10309.    Extension: WideString;
  10310. begin
  10311.   SaveDialog2.Filter := 'vCard files (*.vcf)|*.vcf|XML files (*.xml)|*.xml|';
  10312.   if SaveDialog2.Execute then begin
  10313.      case SaveDialog2.FilterIndex of
  10314.         // sync with ExportList
  10315.         1: Extension := '.vcf';
  10316.         2: Extension := '.xml';
  10317.         //3
  10318.         //4
  10319.      end;
  10320.      if ExtractFileExt(SaveDialog2.FileName) = Extension then
  10321.          frmSIMEdit.ExportList(SaveDialog2.FilterIndex, SaveDialog2.FileName)
  10322.      else
  10323.          frmSIMEdit.ExportList(SaveDialog2.FilterIndex, SaveDialog2.FileName + Extension);
  10324.   end;
  10325. end;
  10326.  
  10327. procedure TForm1.ActionContactsExportUpdate(Sender: TObject);
  10328. begin
  10329.   ActionContactsExportME.Update;
  10330.   ActionContactsExportSM.Update;
  10331.   ActionContactsExport.Enabled := ActionContactsExportME.Enabled or ActionContactsExportSM.Enabled;
  10332. end;
  10333.  
  10334. procedure TForm1.ActionContactsExportExecute(Sender: TObject);
  10335. begin
  10336.   ActionContactsExportME.Execute;
  10337.   ActionContactsExportSM.Execute;
  10338. end;
  10339.  
  10340. procedure TForm1.ActionContactsImportSMUpdate(Sender: TObject);
  10341. begin
  10342.   (Sender as TAction).Enabled := frmSIMEdit.Visible;
  10343. end;
  10344.  
  10345. procedure TForm1.ActionContactsImportSMExecute(Sender: TObject);
  10346. begin
  10347.   frmSIMEdit.ImportContacts1.Click;
  10348. end;
  10349.  
  10350. procedure TForm1.ActionContactsImportUpdate(Sender: TObject);
  10351. begin
  10352.   ActionContactsImportME.Update;
  10353.   ActionContactsImportSM.Update;
  10354.   ActionContactsImport.Enabled := ActionContactsImportME.Enabled or ActionContactsImportSM.Enabled;
  10355. end;
  10356.  
  10357. procedure TForm1.ActionContactsImportExecute(Sender: TObject);
  10358. begin
  10359.   ActionContactsImportME.Execute;
  10360.   ActionContactsImportSM.Execute;
  10361. end;
  10362.  
  10363. function TForm1.IsMoveToArchiveEnabled: boolean;
  10364. begin
  10365.   Result := FMsgM and FTextMessageOptions.MoveToArchive;
  10366. end;
  10367.  
  10368. function TForm1.ExtractContact(ContactNumber: WideString): WideString;
  10369. var
  10370.   i: integer;
  10371. begin
  10372.   i := Pos(' [',ContactNumber);
  10373.   if i = 0 then i := Length(ContactNumber)+1;
  10374.   Result := Copy(ContactNumber,1,i-1);
  10375. end;
  10376.  
  10377. function TForm1.GetChatWindow(Contact: string; AllowCreateNew: boolean): TfrmCharMessage;
  10378. var
  10379.   i: integer;
  10380.   s: string;
  10381.   w: WideString;
  10382. begin
  10383.   Result := nil;
  10384.   w := ExtractContact(Contact);
  10385.   if WideCompareText(w,Contact) = 0 then begin // only number specified
  10386.     s := w;
  10387.     w := LookupContact(w,sUnknownContact);
  10388.   end
  10389.   else
  10390.     s := ExtractNumber(Contact);
  10391.   for i := 0 to Screen.FormCount-1 do
  10392.     if Screen.Forms[i] is TfrmCharMessage then
  10393.       if (Screen.Forms[i] as TfrmCharMessage).IsYourNumber(s) then begin
  10394.         Result := (Screen.Forms[i] as TfrmCharMessage);
  10395.         break;
  10396.       end;
  10397.   if AllowCreateNew and not Assigned(Result) then begin
  10398.     Result := TfrmCharMessage.Create(nil);
  10399.     Result.AddRecipient(w + ' [' + s + ']');
  10400.   end;
  10401.   if Assigned(Result) then Result.AlphaBlendValue := FAlphaCompose;
  10402. end;
  10403.  
  10404. procedure TForm1.ActionContactsNewChatUpdate(Sender: TObject);
  10405. begin
  10406.   ActionContactsNewChat.Enabled := IsContactNumberSelected and (LocateSelContactNumber <> sUnknownNumber);
  10407. end;
  10408.  
  10409. procedure TForm1.ActionContactsNewChatExecute(Sender: TObject);
  10410. var
  10411.   Number: string;
  10412.   Chat: TfrmCharMessage;
  10413. begin
  10414.   Number := LocateSelContactNumber;
  10415.   if Number <> '' then begin
  10416.     Chat := GetChatWindow(Number,True);
  10417.     Chat.Show;
  10418.     Chat.BringToFront;
  10419.     Chat.Memo.SetFocus;
  10420.   end;
  10421. end;
  10422.  
  10423. procedure TForm1.ChatNotifyDel(PDU: String);
  10424. var
  10425.   sms: TSMS;
  10426.   chat: TfrmCharMessage;
  10427. begin
  10428.   try
  10429.     sms := Tsms.Create;
  10430.     try
  10431.       sms.PDU := PDU;
  10432.       chat := GetChatWindow(sms.Number);
  10433.       if Assigned(chat) then begin
  10434.         chat.AddChatText('(Sending canceled, message removed from Outbox)');
  10435.         chat.EnableSending(False);
  10436.       end;
  10437.     finally
  10438.       sms.Free;
  10439.     end;
  10440.   except
  10441.   end;
  10442. end;
  10443.  
  10444. procedure TForm1.HandleCPMS(AMsg: String);
  10445. const
  10446.   LastWarnTime: TDateTime = 0;
  10447.   LimitPercent = 95;
  10448. var
  10449.   str,location: String;
  10450.   used,total,limit: integer;
  10451. begin
  10452.   // FLastMessageStore points XX in last command AT+CPMS="XX",...
  10453.   // +CPMS: <used1>,<total1>,<used2>,<total2>,<used3>,<total3>
  10454.   if FTextMessageOptions.FullWarning then begin
  10455.     str := copy(AMsg, 8, length(AMsg));
  10456.     used := StrToInt(GetToken(str,0));
  10457.     total := StrToInt(GetToken(str,1));
  10458.     limit := Round(total * LimitPercent / 100);
  10459.     if FLastMessageStore = 'ME' then location := 'Phone' else
  10460.     if FLastMessageStore = 'SM' then location := 'SIM' else
  10461.       location := FLastMessageStore;
  10462.     if used >= limit then
  10463.       if ((Now - LastWarnTime) * SecsPerDay) > 300 then begin
  10464.         LastWarnTime := Now;
  10465.         str := location+' message storage is '+IntToStr(LimitPercent)+'% or more full. Please delete some messages.';
  10466.         Status(str);
  10467.         Debug(FLastMessageStore+' memory storage is almost full!');
  10468.         ShowBaloonInfo(str);
  10469.       end;
  10470.   end;
  10471. end;
  10472.  
  10473. procedure TForm1.InitBookmarks;
  10474. var
  10475.   j: integer;
  10476.   it: TStringList;
  10477.   grp: TTntTreeNode;
  10478.   s: WideString;
  10479. begin
  10480.   grp := FNodeBookmarks;
  10481.   grp.DeleteChildren;
  10482.   TStrings(grp.Data).Clear;
  10483.   if frmInfoView.Visible then EBCAState(False);
  10484.   { Retrieve Bookmarks now }
  10485.   it := TStringList.Create;
  10486.   try
  10487.     Debug('Loading bookmarks...');
  10488.     TxAndWait('AT*EWBA?');
  10489.     it.Clear;
  10490.     it.AddStrings(FRxBuffer);
  10491.     for j := 0 to it.Count - 2 do begin
  10492.       if pos('*EWBA', it[j]) = 1 then begin
  10493.         s := it[j];
  10494.         if FUseUTF8 then s := UTF8Decode(s);
  10495.         System.Delete(s,1,7);
  10496.         TStrings(grp.Data).Add(s);
  10497.       end;
  10498.     end;
  10499.     { update explorer and BM view }
  10500.     RenderBookmarkList(grp);
  10501.     if not CoolTrayIcon1.CycleIcons then
  10502.       Status('');
  10503.   finally
  10504.     it.Free;
  10505.     if frmInfoView.Visible then EBCAState(True);
  10506.     if frmExplore.Visible then frmExplore.RootNode := Explorer.Selected;
  10507.   end;
  10508. end;
  10509.  
  10510. procedure TForm1.ActionToolsWapHomepageUpdate(Sender: TObject);
  10511. begin
  10512.   ActionToolsWapHomepage.Enabled := not FBusy and FConnected;
  10513. end;
  10514.  
  10515. procedure TForm1.RenderBookmarkList(var rootNode: TtntTreeNode);
  10516. var
  10517.   sl: TStrings;
  10518.   i: integer;
  10519. begin
  10520.   sl := rootNode.Data;
  10521.   rootNode.DeleteChildren;
  10522.   for i := 0 to sl.Count-1 do
  10523.     with Explorer.Items.AddChild(rootNode,GetToken(sl[i],2)) do begin
  10524.       ImageIndex := 59;
  10525.       StateIndex := StrToInt(GetToken(sl[i],0));
  10526.     end;
  10527.   if frmExplore.Visible then ExplorerChange(nil,Explorer.Selected);
  10528. end;
  10529.  
  10530. procedure TForm1.ActionToolsWapHomepageExecute(Sender: TObject);
  10531. var
  10532.   s: WideString;
  10533.   i: integer;
  10534. begin
  10535.   { Get max URL length }
  10536.   try
  10537.     TxAndWait('AT*EWHP=?');
  10538.   except
  10539.     raise EInOutError.Create('Could not change WAP home page!'#13#13+
  10540.       'In certain terminals a number of WAP profiles may be locked at '+
  10541.       'manufacturing to prevent the users from altering the predefined WAP settings. When such a '+
  10542.       'profile is active some of the commands in this ensemble will not function according to '+
  10543.       'specification. The read and test commands should always function as expected but the set '+
  10544.       'command will return ERROR even though the command is given using the correct syntax and '+
  10545.       'all parameters are within range.');
  10546.   end;
  10547.   s := FRxBuffer[0];
  10548.   Delete(s,1,7);
  10549.   i := StrToInt(s);
  10550.   { Get current home page }
  10551.   TxAndWait('AT*EWHP?');
  10552.   s := FRxBuffer[0];
  10553.   Delete(s,1,7);
  10554.   s := GetToken(s,0); // trim and remove quotes
  10555.   if s = '' then s := 'http://';
  10556.   if WideInputQuery('Edit Wap Home Page','Enter URL:',s) and (Trim(s) <> '') and (s <> 'http://') then begin
  10557.     { Set new page }
  10558.     s := Copy(s,1,i);
  10559.     { Do not UTF-8 here, or should we? i18n url are possible not }
  10560.     if FUseUTF8 then s := UTF8Encode(s);
  10561.     TxAndWait('AT*EWHP="'+s+'"');
  10562.     Status('Home page changed');
  10563.   end;
  10564. end;
  10565.  
  10566. procedure TForm1.DoRemoveBookmark;
  10567. var
  10568.   Node: PVirtualNode;
  10569.   Item: PExploreItem;
  10570.   num,desc: string;
  10571. begin
  10572.   num := '';
  10573.   if Explorer.Selected = FNodeBookmarks then begin
  10574.     Node := frmExplore.ListItems.FocusedNode;
  10575.     Item := frmExplore.ListItems.GetNodeData(Node);
  10576.     num := Item.param;
  10577.     desc := Item.name;
  10578.   end;
  10579.   if Explorer.Selected.Parent = FNodeBookmarks then begin
  10580.     num := IntToStr(Explorer.Selected.StateIndex);
  10581.     desc := Explorer.Selected.Text;
  10582.   end;
  10583.   if num <> '1' then begin // bookmark at pos 1 is reserved
  10584.     if MessageDlg('Are you sure you want to delete the bookmark "'+desc+'"?',
  10585.       mtConfirmation,[mbYes,mbNo],0) = ID_YES then begin
  10586.       RequestConnection;
  10587.       TxAndWait('AT*EWBA='+num+','); // delete
  10588.       InitBookmarks;
  10589.       Status('Delete completed');
  10590.     end;
  10591.   end
  10592.   else
  10593.     raise Exception.Create('Bookmark at position 1 is reserved and can not be deleted');
  10594. end;
  10595.  
  10596. function TForm1.GetDatabasePath: string;
  10597. begin
  10598.   Result := PhoneIdentity;
  10599.   if Result <> '' then
  10600.     Result := ExePath+'data\'+Result+'\dat\';
  10601. end;
  10602.  
  10603. procedure TForm1.EditFavorites1Click(Sender: TObject);
  10604. var
  10605.   sl: TStringList;
  10606. begin
  10607.   with TfrmOrganizeFavs.Create(nil) do
  10608.     try
  10609.       FavsType := 'Message Recipients';
  10610.       FavsList := FFavoriteRecipients;
  10611.       { Allow multiple contacts per a favorite record }
  10612.       // MultiSel := True; { default setting }
  10613.       if ShowModal = mrOk then begin
  10614.         { Result from FavsList should be handled here, i.e. free-ed manualy! }
  10615.         sl := FavsList;
  10616.         try
  10617.           FFavoriteRecipients.Assign(sl);
  10618.         finally
  10619.           sl.Free;
  10620.         end;
  10621.       end;
  10622.     finally
  10623.       Free;
  10624.     end;
  10625. end;
  10626.  
  10627. procedure TForm1.EditCallFavorites1Click(Sender: TObject);
  10628. var
  10629.   sl: TStringList;
  10630. begin
  10631.   with TfrmOrganizeFavs.Create(nil) do
  10632.     try
  10633.       FavsType := 'Call Recipients';
  10634.       FavsList := FFavoriteCalls;
  10635.       { Allow only one contact per a favorite record }
  10636.       MultiSel := False;
  10637.       if ShowModal = mrOk then begin
  10638.         { Result from FavsList should be handled here, i.e. free-ed manualy! }
  10639.         sl := FavsList;
  10640.         try
  10641.           FFavoriteCalls.Assign(sl);
  10642.         finally
  10643.           sl.Free;
  10644.         end;
  10645.       end;
  10646.     finally
  10647.       Free;
  10648.     end;
  10649. end;
  10650.  
  10651. procedure TForm1.ActionContactsVoiceHangupUpdate(Sender: TObject);
  10652. begin
  10653.   ActionContactsVoiceHangup.Enabled := FConnected and not FObex.Connected and
  10654.     (frmCalling <> nil) and (frmCalling.IsTalking or frmCalling.IsCalling);
  10655. end;
  10656.  
  10657. procedure TForm1.ActionContactsVoiceHangupExecute(Sender: TObject);
  10658. begin
  10659.   frmCalling.HandupButton.Click;
  10660. end;
  10661.  
  10662. procedure TForm1.ApplicationEvents1Hint(Sender: TObject);
  10663. begin
  10664.   if not FConnectingStarted or FConnectingComplete then Status(Application.Hint,False);
  10665. end;
  10666.  
  10667. procedure TForm1.ActionToolsCreateGroupExecute(Sender: TObject);
  10668. var
  10669.   s: WideString;
  10670. begin
  10671.   s := 'New Group';
  10672.   if WideInputQuery('Create New Group','Enter group name:',s) and (Trim(s) <> '') then begin
  10673.     RequestConnection;
  10674.     if FUseUTF8 then s := UTF8Encode(s);
  10675.     TxAndWait('AT*ESCG="'+s+'"');
  10676.     InitGroups;
  10677.     Status('Group created');
  10678.   end;
  10679. end;
  10680.  
  10681. procedure TForm1.DoRemoveGroup;
  10682. var
  10683.   Node: PVirtualNode;
  10684.   Item: PExploreItem;
  10685.   num,desc: string;
  10686. begin
  10687.   if Explorer.Selected = FNodeGroups then begin
  10688.     Node := frmExplore.ListItems.FocusedNode;
  10689.     Item := frmExplore.ListItems.GetNodeData(Node);
  10690.     num := Item.param;
  10691.     desc := Item.name;
  10692.     if MessageDlg('Are you sure you want to delete the group "'+desc+'"?',
  10693.       mtConfirmation,[mbYes,mbNo],0) = ID_YES then begin
  10694.       RequestConnection;
  10695.       TxAndWait('AT*ESDG='+num); // delete
  10696.       InitGroups;
  10697.       Status('Delete completed');
  10698.     end;
  10699.   end;
  10700. end;
  10701.  
  10702. procedure TForm1.SyncBookmarks1Click(Sender: TObject);
  10703. begin
  10704.   MessageDlg('This feature is not implemented yet!',mtError,[mbOk],0);
  10705. end;
  10706.  
  10707. procedure TForm1.ActionToolsPostBookmarkUpdate(Sender: TObject);
  10708. begin
  10709.   ActionBusyUpdate(ActionToolsPostBookmark);
  10710.   if not FConnected then ActionToolsPostBookmark.Enabled := False;
  10711. end;
  10712.  
  10713. function TForm1.ObexFolderPath(Node: TtntTreeNode): WideString;
  10714. begin
  10715.   Result := '';
  10716.   while Node <> FNodeObex do begin
  10717.     Result := Node.Text + '/' + Result;
  10718.     Node := Node.Parent;
  10719.   end;
  10720.   { Result includes root folder and trailing slash }
  10721.   Result := '/' + Result;
  10722. end;
  10723.  
  10724. procedure TForm1.ActionToolsSilentUpdate(Sender: TObject);
  10725. begin
  10726.   ActionToolsSilent.Checked := FSilentMode;
  10727.   ActionToolsSilent.ImageIndex := 57 + byte(FSilentMode);
  10728.   if FSilentMode then ActionToolsSilent.Caption := 'Disable &Silent Mode'
  10729.     else ActionToolsSilent.Caption := 'Enable &Silent Mode';
  10730.   if not FConnected or FObex.Connected or FObexConnecting then
  10731.     ActionToolsSilent.Enabled := False;
  10732. end;
  10733.  
  10734. procedure TForm1.ActionToolsSilentExecute(Sender: TObject);
  10735. begin
  10736.   TxAndWait('AT*ESIL='+IntToStr(byte(not FSilentMode)));
  10737.   FSilentMode := not FSilentMode;
  10738. end;
  10739.  
  10740. procedure TForm1.ActionToolsPowerOffExecute(Sender: TObject);
  10741. begin
  10742.   MessageBeep(MB_ICONQUESTION);
  10743.   if MessageDlg('Are you sure you want to disconnect and power your phone off?',
  10744.     mtConfirmation,[mbYes,mbNo],0) = ID_YES then begin
  10745.     TxAndWait('AT+CFUN=0');
  10746.     ActionConnectionDisconnect.Execute;
  10747.   end;
  10748. end;
  10749.  
  10750. end.
  10751.  
  10752.